使用redis做为MySQL的缓存

 

介绍

  • 在实际项目中,MySQL数据库服务器有时会位于另外一台主机,需要通过网络来访问数据库;即使应用程序与MySQL数据库在同一个主机中,访问MySQL也涉及到磁盘IO操作(MySQL也有一些数据预读技术,能够减少磁盘IO读写,此部分后续继续研究),总之,直接从MySQL中读取数据不如直接从内存中读取数据来的效率高。为了提高数据库访问效率,人们采用了各种各样的方法,其中方法之一就是使用一个给予内存的缓存系统放置在数据库和应用程序之间。在查找数据的时候,首先从内存中查找,如果找到则使用,如果没有找到,那么再真正访问数据库。这种方法在一些场景下(例如:频繁查找相同数据)能够提高系统的整体效率。
  • 本文的主要目的即介绍上文说的这样一种方法,采用redis nosql数据库作为Mysql数据库的缓存,在查找的时候,首先查找redis缓存,如果找到则返回结果;如果在redis中没有找到,那么查找Mysql数据库,找到的花则返回结果并且更新redis;如果没有找到则返回空。对于写入的情况,直接写入mysql数据库,mysql数据库通过触发器及UDF机制自动把变更的内容更新到redis中。

框图

  读取步骤:

  1. 1. client读取redis,如果命中返回结果,如果没有命中转到2.
    2. client读取数据库,在数据库中没有查到,返回空;在数据库中查到了,返回查到的结果并更新Redis。
  2. 写入步骤:
    1. client修改/删除或者新增数据到MySQL。
    2. MySQL的触发器调用用户自定义的UDF。
    3. UDF把修改/删除或者新增的数据更新到redis中。

代码实现

软件需求

  • redis server与client安装,redis编程相关的c库。
  • mysql server安装,mysql-devel包的安装,此包包含操作mysql数据库的C语言API包。
  • -

实现步骤

1. 安装并验证redis

127.0.0.1:6379> hgetall w3ckey
(empty list or set) #最开始在reids中没有w3ckey的K-V对。
127.0.0.1:6379>

2. 安装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;
}     /*
      //如果设有密码为ubuntu
       redisReply *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_redis
after insert on test1
for each row
begin
declare 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_redis
after update on test1
for each row
begin
declare ret int;
select gxupdate(NEW.id, NEW.name, NEW.age, NEW.description) into @ret;
end| create trigger delete_redis
after delete on test1
for each row
begin
declare 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

redis 作为 mysql的缓存的更多相关文章

  1. redis作为mysql的缓存服务器(读写分离,通过mysql触发器实现数据同步)

    一.redis简介Redis是一个key-value存储系统.和Memcached类似,为了保证效率,数据都是缓存在内存中.区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录 ...

  2. redis作为mysql的缓存服务器(读写分离) (转)

    一.redis简介Redis是一个key-value存储系统.和Memcached类似,为了保证效率,数据都是缓存在内存中.区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录 ...

  3. 用Redis作Mysql数据库缓存

    使用redis作mysql数据库缓存时,需要考虑两个问题: 1.确定用何种数据结构存储来自Mysql的数据; 2.在确定数据结构之后,用什么标识作为该数据结构的键. 直观上看,Mysql中的数据都是按 ...

  4. redis(二)--用Redis作MySQL数据库缓存

    用Redis作MySQL数据库缓存,必须解决2个问题.首先,应该确定用何种数据结构存储来自mysql的数据:在确定数据结构之后,还要考虑用什么标识作为该数据结构的键. 直观上看,Mysql中的数据都是 ...

  5. redis作为mysql的缓存服务器(读写分离)

    转自:https://www.iyunv.com/thread-52670-1-1.html 一.redis简介Redis是一个key-value存储系统.和Memcached类似,为了保证效率,数据 ...

  6. redis 作为 mysql的缓存服务器(读写分离)

    redis 作为 mysql的缓存服务器(读写分离) 一.redis简介 Redis是一个key-value存储系统.和Memcached类似,为了保证效率,数据都是缓存在内存中.区别的是redis会 ...

  7. 如何使用Redis做MySQL的缓存

    应用Redis实现数据的读写,同时利用队列处理器定时将数据写入mysql. 同时要注意避免冲突,在redis启动时去mysql读取所有表键值存入redis中,往redis写数据时,对redis主键自增 ...

  8. 用Redis作为Mysql数据库的缓存【转】

    用Redis作Mysql数据库缓存,必须解决2个问题.首先,应该确定用何种数据结构存储来自Mysql的数据:在确定数据结构之后,还要考虑用什么标识作为该数据结构的键. 直观上看,Mysql中的数据都是 ...

  9. lnmp一键安装环境添加redis扩展及作为mysql的缓存

    lnmp一键安装环境添加redis扩展 Redis-benchmark      压力测试工具Redis-check-aof      检查redis持久化命令文件的完整性Redis-check-du ...

随机推荐

  1. Windows Azure 部署 Windows 8 虚拟机

    基本步骤其实很简单,主要有: 本地部署虚拟机 将虚拟机VHD上传至Azure 在Azure上根据VHD生成映像 利用映像生成虚拟机 下面我们开始: 1,本地部署虚拟机 首先我们需要在本地用 Hyper ...

  2. chkconfig命令 centos 开机启动命令

    .利用 chkconfig 来配置启动级别 在CentOS或者RedHat其他系统下,如果是后面安装的服务,如httpd.mysqld.postfix等,安装后系统默认不会自动启动的.就算手动执行 / ...

  3. java 环境安装

    因为现在的java安装需要点击同意许可才能安装,造成了在linux中使用wget命令下载无法正常完整下载,即便下载下来也是不完整的 安装会提示 no such file等一堆提示 我们使用参数如下的命 ...

  4. Centos安装Samba共享服务器

    安装Samba 查看Samba是否已安装 1.# rpm -qa | grep samba

  5. Nginx编译安装:

    第三方模块 在nginx.org   --------  wiki  找 --add-module=   添加 Nginx编译安装: 安装开发环境 ]# yum groupinstall " ...

  6. Codeforces 356D Bacterial Melee dp

    Bacterial Melee 我们发现所有合法串都是原序列的某个子序列(这个子序列相邻元素相等) 的扩展, 比如子序列为abc, 那么aabbbc, abbbcc 等都是合法串. 所以我们只需要dp ...

  7. PHP中使用CURL实现GET和POST请求(转载)

    CURL 是一个利用URL语法规定来传输文件和数据的工具,支持很多协议,如HTTP.FTP.TELNET等.最爽的是,PHP也支持 CURL 库.使用PHP的CURL 库可以简单和有效地去抓网页.你只 ...

  8. debian9 开启rc.local服务

    由于某些软件并没有增加开启启动的服务,很多时候需要手工添加,一般我们都是推荐添加命令到 /etc/rc.local 文件,但是 Debian 9 默认不带 /etc/rc.local 文件,而 rc. ...

  9. 大数据技术 - MapReduce的Shuffle及调优

    本章内容我们学习一下 MapReduce 中的 Shuffle 过程,Shuffle 发生在 map 输出到 reduce 输入的过程,它的中文解释是 “洗牌”,顾名思义该过程涉及数据的重新分配,主要 ...

  10. mongoose之操作mongoDB数据库

    mongoose是node.js操作mongoDB数据库的一种工具,借助于mongoose,我们可以便捷的完成一些数据库的基本操作,基本使用如下: 1.安装 npm install mongoose ...