使用redis做為MySQL的緩存

介紹
在實際項目中,MySQL數據庫服務器有時會位于另外一臺主機,需要通過網絡來訪問數據庫;即使應用程序與MySQL數據庫在同一個主機中,訪問MySQL也涉及到磁盤IO操作(MySQL也有一些數據預讀技術,能夠減少磁盤IO讀寫,此部分后續繼續研究),總之,直接從MySQL中讀取數據不如直接從內存中讀取數據來的效率高。為了提高數據庫訪問效率,人們采用了各種各樣的方法,其中方法之一就是使用一個給予內存的緩存系統放置在數據庫和應用程序之間。在查找數據的時候,首先從內存中查找,如果找到則使用,如果沒有找到,那么再真正訪問數據庫。這種方法在一些場景下(例如:頻繁查找相同數據)能夠提高系統的整體效率。
本文的主要目的即介紹上文說的這樣一種方法,采用redis nosql數據庫作為Mysql數據庫的緩存,在查找的時候,首先查找redis緩存,如果找到則返回結果;如果在redis中沒有找到,那么查找Mysql數據庫,找到的花則返回結果并且更新redis;如果沒有找到則返回空。對于寫入的情況,直接寫入mysql數據庫,mysql數據庫通過觸發器及UDF機制自動把變更的內容更新到redis中。
框圖
  讀取步驟:

  1. client讀取redis,如果命中返回結果,如果沒有命中轉到2.
  2. client讀取數據庫,在數據庫中沒有查到,返回空;在數據庫中查到了,返回查到的結果并更新Redis。
    寫入步驟:
  3. client修改/刪除或者新增數據到MySQL。
  4. MySQL的觸發器調用用戶自定義的UDF。
  5. UDF把修改/刪除或者新增的數據更新到redis中。
    代碼實現
    軟件需求
    redis server與client安裝,redis編程相關的c庫。
    mysql server安裝,mysql-devel包的安裝,此包包含操作mysql數據庫的C語言API包。

實現步驟
6. 安裝并驗證redis

127.0.0.1:6379> hgetall w3ckey
(empty list or set)    #最開始在reids中沒有w3ckey的K-V對。
127.0.0.1:6379>
  1. 安裝MySQL數據庫服務器
    2.1 創建MySQL數據庫的腳本如下
drop database if exists mysqlRedis;
create database mysqlRedis;
use mysqlRedis;create table test1(id INT NOT NULL AUTO_INCREMENT,name VARCHAR(64),age INT,description VARCHAR(1000),primary key(id));

2.2 創建UDF使用的動態庫

#include <stdio.h>
#include <stdlib.h>
#include <mysql.h>
#include <string.h>
#include <hiredis/hiredis.h>int gxupdate(UDF_INIT * initid, UDF_ARGS * args, char * is_null, char * error) {redisContext * c = redisConnect("127.0.0.1", 6379);if(c->err) {redisFree(c);return 1;}/*//如果設有密碼為ubunturedisReply *reply;char strReply[] = "AUTH ubuntu";reply = (redisReply*)redisCommand(c, strReply);freeReplyObject(reply);reply = NULL;*/const char * command1 = "HMSET w3ckey id %d name %s age %d description %s";redisReply * r = (redisReply *)redisCommand(c, command1,*(int*)args->args[0], args->args[1], *(int *)args->args[2], args->args[3]);if (r == NULL) {return 1;}if (!((r->type == REDIS_REPLY_STATUS) && (strcasecmp(r->str, "OK") == 0))) {freeReplyObject(r);redisFree(c);return 1;}freeReplyObject(r);return 0;
}my_bool gxupdate_init(UDF_INIT * initid, UDF_ARGS * args, char * message) {return 0;
}

編譯為動態庫:
gcc -shared -fPIC -I /usr/include/mysql -o udfredis.so mysqlUDFdemo.c /usr/local/lib/libhiredis.a
編譯完成之后拷貝動態庫udfgx.so到 /usr/lib/mysql/plugin/文件夾中,并修改成用戶對應權限。

2.3 配置udf與trigger。

use mysqlRedis;drop function if exists gxupdate;
create function gxupdate returns INTEGER soname "udfredis.so";drop trigger if exists insert_redis;
drop trigger if exists update_redis;
drop trigger if exists delete_redis;delimiter |create trigger insert_redisafter insert on test1for each rowbegindeclare ret int;select gxupdate(NEW.id, NEW.name, NEW.age, NEW.description) into @ret;
#必須加into @ret,否則返回錯誤ERROR 1415 (0A000) 
#at line 6: Not allowed to return a result set from a trigger
#insert只有NEW變量。
#update有NEW和OLD變量。
#delete只有OLD變量。
end|create trigger update_redisafter update on test1for each rowbegindeclare ret int;select gxupdate(NEW.id, NEW.name, NEW.age, NEW.description) into @ret;end|create trigger delete_redisafter delete on test1for each rowbegindeclare ret int;select gxupdate(OLD.id, OLD.name, OLD.age, OLD.description) into @ret;end|delimiter ;

注意,在MySQL中創建UDF的時候,insert, update和delete不能寫成一個觸發器,只能分別定義成三個觸發器。

測試
查看redis

[root@VM_24_16_centos mysql_redis]# redis-cli
127.0.0.1:6379> hgetall w3ckey
(empty list or set)
127.0.0.1:6379> 

redis中無key w3ckey 對應的value。

insert MySQL

mysql> insert into test1 (name, age, description) values ("ggglwlop", 23, "ddddgdg");
Query OK, 1 row affected (0.02 sec)mysql> 

插入mysql。

查看redis

127.0.0.1:6379> hgetall w3ckey
1) "name"
2) "ggglwlop"
3) "description"
4) "ddddgdg"
5) "likes"
6) "27"
7) "visitors"
8) "23"
127.0.0.1:6379> 

MySQL中有了對應的數據,說明mysql通過triger+udf的方式把改動更新到了redis中。

有用的鏈接

http://blog.csdn.net/socho/article/details/52292064
https://www.cnblogs.com/linuxbug/p/4950626.html
https://www.cnblogs.com/tommy-huang/p/4703514.html  使用redis作為mysql緩存時的redis結構設計。
http://blog.csdn.net/shikaiwencn/article/details/51792059    需要根據實際需求來靈活設計redis kv關系。
https://www.cnblogs.com/bruceleeliya/archive/2009/05/23/Linux-C-Mysql.html  使用mysql的C API訪問mysql。
https://www.2cto.com/database/201110/108925.html  #mysql udf。
https://www.cnblogs.com/linuxbug/p/4950626.html  #udf使用的一個例子。
https://www.jianshu.com/p/4381a38403a1
http://blog.csdn.net/socho/article/details/52292064

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/250087.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/250087.shtml
英文地址,請注明出處:http://en.pswp.cn/news/250087.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

[Head First Java] - 給線程命名

參考 - P503 public class RunThreads implements Runnable {public static void main (String[] args) {RunThreads runner new RunThreads();Thread alpha new Thread(runner);Thread beta new Thread(runner);alpha.setName("Alpha thread");beta.setName(&qu…

Cortex-M3 的SVC、PendSV異常,與操作系統(ucos實時系統)(轉)

Cortex-M3 的SVC、PendSV異常&#xff0c;與操作系統(ucos實時系統)轉載于:https://www.cnblogs.com/LittleTiger/p/10070824.html

快速排序的C++版

int Partition(int a[], int low, int high) {int x a[high];//將輸入數組的最后一個數作為主元&#xff0c;用它來對數組進行劃分int i low - 1;//i是最后一個小于主元的數的下標for (int j low; j < high; j)//遍歷下標由low到high-1的數{if (a[j] < x)//如果數小于…

springboot---整合shiro

Shiro是一個非常不錯的權限框架&#xff0c;它提供了登錄和權限驗證功能 1.創建數據庫腳本 SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS 0; -- ---------------------------- -- Table structure for module -- ---------------------------- DROP TABLE IF EXISTS module; C…

[Head First Java] - 線程共享數據問題

參考 - P507 1. 說明 兩個線程共享同一份數據,每次使用數據時,需要先判斷其是否在合理范圍每次使用數據完畢使用Thread.sleep函數讓線程阻塞 2.代碼 class BankAccount {private int balance 100;public int getBalance() {return balance;}public void withdraw(int amou…

asp.net中提交表單數據時提示從客戶端(。。。)中檢測到有潛在危險的 Request.Form 值...

看到這個圖是不是很親切熟悉哈&#xff0c;做過。net的肯定都見過哈 已經 將近4年沒碰。net了&#xff0c;今天正好朋友的程序有幾個bug,讓我幫忙修復下&#xff0c;于是我就抱著試試看的心情改了改&#xff0c;改到最后一個問題的時候也就是上面的這個問題&#xff0c;我一看&…

Openresty編寫Lua代碼一例

1.前段時間糾結了很久&#xff0c;一直弄不清lua和tomcat的聯系。一直認為是lua調用tomcat的接口才可使用&#xff0c;后面才明白過來&#xff0c;進入了一個誤區&#xff0c;lua本身就是一門獨立的腳本語言。在openresty里面配置好&#xff0c;即可編寫映射和響應。 下面是自己…

Shiro表結構設計

表設計 開發用戶-角色-權限管理系統&#xff0c;首先我們需要知道用戶-角色-權限管理系統的表結構設計。 在用戶-角色-權限管理系統找那個一般會涉及5張表&#xff0c;分別為&#xff1a; 1.sys_users用戶表 2.sys_roles角色表 3.sys_permissions權限表&#xff08;或資源表&…

[Java核心技術(卷I)] - 簡易的日歷

參考 - P102~P103 1. 目標 生成一個日歷,格式如下圖所示。 ps: 當前的天數需要標記為* 2. 核心 對日歷的變量 import java.time.*; public class CalendarTest{public static void main(String[] args) {LocalDate date LocalDate.now(); // 獲取當前日期int month date…

個人作業——福大微信公眾號使用評測

案例分析&#xff1a;在福州大學公眾號上&#xff0c;我們可以即時使用手機關注福大新聞&#xff0c;查看自身課表、成績等。公眾號可能存在一些小bug影響同學們的用戶體驗。本次作業中&#xff0c;作為一個用戶——福大的學生&#xff0c;將切身體驗該公眾號的功能&#xff0c…

在winform中使用wpf窗體

在winform項目&#xff0c;通過引用dll可以添加WPF窗體&#xff0c;如下 但是如果直接在winform的項目中添加wpf窗體還是有部分問題&#xff0c;圖片的顯示。 直接在XAML界面中用Source屬性設置圖片會出現錯誤。必須通過后臺代碼的方式來實現。 image1.Source GetImageIcon(gl…

shiro---注解

RequiresAuthentication 驗證用戶是否登錄&#xff0c;等同于方法subject.isAuthenticated() 結果為true時。 RequiresUser 驗證用戶是否被記憶&#xff0c;user有兩種含義&#xff1a; 一種是成功登錄的&#xff08;subject.isAuthenticated() 結果為true&#xff09;&…

[Java核心技術(卷I)] - Java中的參數能做什么和不能做什么

1. 參考 - P123 ~ P126 2. 你將學到 Java中對方法參數能做什么和不能做什么 方法不能修改基本數據類型的參數(數值型或布爾型)方法可以改變對象參數的狀態方法不能讓一個對象參數引用一個新的對象 3. 代碼證明 public class ParamTest {public static void main(String[] ar…

軟件構造 第五章第一節 可復用性的度量、形態和外部觀察

第五章第一節 可復用性的度量、形態和外部觀察 面向復用編程(programming for reuse)&#xff1a;開發出可復用的軟件 基于復用編程(programming with reuse)&#xff1a;利用已有的可復用軟件搭建應用系統 代碼復用的類型&#xff1a; 白盒復用&#xff1a;源代碼可見&#x…

洛谷團隊月賽題:題解

10pts10pts10pts 暴力算不解釋&#xff0c;時間復雜度O(knk2)O(knk^2)O(knk2)。 30pts30pts30pts 我們觀察到nnn很大&#xff0c;楊輝三角會T&#xff0c;直接算會上溢&#xff0c;所以需要預處理出111~kkk逆元再算&#xff0c;時間復雜度O(knnlogkn2)O(knnlogkn^2)O(knnlogkn2…

Angular Forms - 自定義 ngModel 綁定值的方式

在 Angular 應用中&#xff0c;我們有兩種方式來實現表單綁定——“模板驅動表單”與“響應式表單”。這兩種方式通常能夠很好的處理大部分的情況&#xff0c;但是對于一些特殊的表單控件&#xff0c;例如input[typedatetime]、input[typefile]&#xff0c;我們需要重寫默認的表…

[web性能優化] - 使用在線工具對html、js、css進行壓縮

參考 1. 學習點 使用 在線工具對html、css、js進行壓縮學會分析壓縮前后的效率提高點 2. 解決方案: 2.1 HTML壓縮 在線壓縮nodejs提供了 html-minifier工具(在構建層對代碼進行壓縮)后端模板引擎渲染壓縮 2.2 CSS壓縮 使用html-minifier對html中的css進行壓縮使用clean-cs…

【LOJ】 #2540. 「PKUWC2018」隨機算法

題解 感覺極其神奇的狀壓dp \(dp[i][S]\)表示答案為i&#xff0c;然后不可選的點集為S 我們每次往答案里加一個點&#xff0c;然后方案數是&#xff0c;設原來可以選的點數是y&#xff0c;新加入一個點后導致了除了新加的點之外x個點不能選&#xff0c;那么方案就是把x個數在y …

Shiro的authc過濾器的執行流程

1.先執行isAccessAllowed()&#xff0c;通過subject.isAuthenticated()判斷當前session中的subject是否已經登陸過。如果在當前session即會話中已經登陸過&#xff0c;返回true&#xff0c;authc過濾器放行請求到loginUrl。 問題? 這里會有一個問題&#xff0c;如果我登陸成功…

SpringBoot之基礎

簡介 背景 J2EE笨重的開發 / 繁多的配置 / 低下的開發效率 / 復雜的部署流程 / 第三方技術集成難度大 特點 ① 快速創建獨立運行的spring項目以及主流框架集成 ② 使用嵌入式的Servlet容器, 應用無需達成war包 ③ starters自動依賴和版本控制 ④ 大量自動配置, 簡化開發, 也可修…