使用redis做为MySQL的缓存-C语言编写UDF
介绍
在实际项目中,MySQL数据库服务器有时会位于另外一台主机,需要通过网络来访问数据库;即使应用程序与MySQL数据库在同一个主机中,访问MySQL也涉及到磁盘IO操作(MySQL也有一些数据预读技术,能够减少磁盘IO读写,此部分后续继续研究),总之,直接从MySQL中读取数据不如直接从内存中读取数据来的效率高。为了提高数据库访问效率,人们采用了各种各样的方法,其中方法之一就是使用一个给予内存的缓存系统放置在数据库和应用程序之间。在查找数据的时候,首先从内存中查找,如果找到则使用,如果没有找到,那么再真正访问数据库。这种方法在一些场景下(例如:频繁查找相同数据)能够提高系统的整体效率。
本文的主要目的即介绍上文说的这样一种方法,采用redis nosql数据库作为Mysql数据库的缓存,在查找的时候,首先查找redis缓存,如果找到则返回结果;如果在redis中没有找到,那么查找Mysql数据库,找到的花则返回结果并且更新redis;如果没有找到则返回空。对于写入的情况,直接写入mysql数据库,mysql数据库通过触发器及UDF机制自动把变更的内容更新到redis中。
框图
这里写图片描述 读取步骤:
. client读取redis,如果命中返回结果,如果没有命中转到2.
. client读取数据库,在数据库中没有查到,返回空;在数据库中查到了,返回查到的结果并更新Redis。
写入步骤:
. client修改/删除或者新增数据到MySQL。
. MySQL的触发器调用用户自定义的UDF。
. UDF把修改/删除或者新增的数据更新到redis中。
代码实现
软件需求
redis server与client安装,redis编程相关的c库。
mysql server安装,mysql-devel包的安装,此包包含操作mysql数据库的C语言API包。
-
实现步骤
. 安装并验证redis
127.0.0.1:> hgetall w3ckey
(empty list or set) #最开始在reids中没有w3ckey的K-V对。
127.0.0.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(),
age INT,
description VARCHAR(),
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", );
if(c->err) {
redisFree(c);
return ;
} const char * command1 = "HMSET w3ckey name %s description %s likes %d visitors %d";
redisReply * r = (redisReply *) redisCommand(c, command1,
args->args[], args->args[], *(int *)args->args[], *(int *)args->args[]);
if(r == NULL) {
return ;
}
if(!((r->type == REDIS_REPLY_STATUS) && (strcasecmp(r->str, "OK") == ))) {
freeReplyObject(r);
redisFree(c);
return ;
}
freeReplyObject(r);
return ;
} my_bool gxupdate_init(UDF_INIT * initid, UDF_ARGS * args, char * message) {
return ;
} 编译为动态库: gcc -shared -fPIC -I /usr/include/mysql -o udfgx.so mysqlUDFdemo.c /usr/local/lib/libhiredis.a 编译完成之后拷贝动态库udfgx.so到 /usr/lib64/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 (0A000)
#at line : 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:> hgetall w3ckey
(empty list or set)
127.0.0.1:> redis中无key w3ckey 对应的value。 insert MySQL
mysql> insert into test1 (name, age, description) values ("ggglwlop", , "ddddgdg");
Query OK, row affected (0.02 sec) mysql> 插入mysql。 查看redis
127.0.0.1:> hgetall w3ckey
) "name"
) "ggglwlop"
) "description"
) "ddddgdg"
) "likes"
) ""
) "visitors"
) ""
127.0.0.1:> 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的缓存-C语言编写UDF的更多相关文章
- 使用Redis做为MySQL的缓存
OS: Ubuntu 16.04.4 x64 更新并安装必要的工具 apt update && apt upgrade -y && apt dist-upgrade - ...
- 使用Redis做MyBatis的二级缓存
使用Redis做MyBatis的二级缓存 通常为了减轻数据库的压力,我们会引入缓存.在Dao查询数据库之前,先去缓存中找是否有要找的数据,如果有则用缓存中的数据即可,就不用查询数据库了. 如果没有才去 ...
- 使用redis做mybaties的二级缓存(2)-Mybatis 二级缓存小心使用
Mybatis默认对二级缓存是关闭的,一级缓存默认开启: 下面就说说为什么使用二级缓存需要注意: 二级缓存是建立在同一个namespace下的,如果对表的操作查询可能有多个namespace,那么得到 ...
- redis 作为 mysql的缓存
使用redis做为MySQL的缓存 介绍 在实际项目中,MySQL数据库服务器有时会位于另外一台主机,需要通过网络来访问数据库:即使应用程序与MySQL数据库在同一个主机中,访问MySQL也涉及到 ...
- sping整合redis,以及做mybatis的第三方缓存
一.spring整合redis Redis作为一个时下非常流行的NOSQL语言,不学一下有点过意不去. 背景:学习Redis用到的框架是maven+spring+mybatis(框架如何搭建这边就不叙 ...
- 如何使用Redis做MySQL的缓存
应用Redis实现数据的读写,同时利用队列处理器定时将数据写入mysql. 同时要注意避免冲突,在redis启动时去mysql读取所有表键值存入redis中,往redis写数据时,对redis主键自增 ...
- 使用redis做mysql缓存
应用Redis实现数据的读写,同时利用队列处理器定时将数据写入mysql. 同时要注意避免冲突,在redis启动时去mysql读取所有表键值存入redis中,往redis写数据时,对redis主键自增 ...
- springboot2.0+redis实现消息队列+redis做缓存+mysql
本博客仅供参考,本人实现没有问题. 1.环境 先安装redis.mysql 2.springboot2.0的项目搭建(请自行完成),本人是maven项目,因此只需配置,获取相应的jar包,配置贴出. ...
- redis作为mysql的缓存服务器(读写分离,通过mysql触发器实现数据同步)
一.redis简介Redis是一个key-value存储系统.和Memcached类似,为了保证效率,数据都是缓存在内存中.区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录 ...
随机推荐
- vue 下拉框单选、多选以及默认值
背景: 单选框和多选框 都是使用了 el-select,但传给后端的值类型不一样,多选框传的值是 list类型: ['value1','value2'] ,单选框传值和其他类型一样:设置默认值也是如此 ...
- Pthon操作Gitlab API----批量删除,创建,取消保护
1.需求:大批量的应用上线后合并到Master,其他的分支develop/test/uat等需要同步最新代码的操作. 2.操作:可以通过传参 ,列表 的方式把每个项目的id值填入,才能对相关项目进行批 ...
- django.db.models.fields.related_descriptors.RelatedObjectDoesNotExist
Enrollment has no customer.
- CSP模拟赛 Repulsed(树形DP)
题面 ⼩ w ⼼⾥的⽕焰就要被熄灭了. 简便起⻅,假设⼩ w 的内⼼是⼀棵 n − 1 条边,n 个节点的树. 现在你要在每个节点⾥放⼀些个灭⽕器,每个节点可以放任意多个. 接下来每个节点都要被分配给 ...
- hive优化,开启压缩功能
1.开启hive作业mapreduce任务中间压缩功能: 对于数据进行压缩可以减少job中map和reduce task间的数据传输量.对于中间数据压缩,选择一个低cpu开销编/解码器要不选择一个压缩 ...
- NodeJS后台
NodeJS后台 后台: 1.PHP 2.Java 3.Python 优势 1.性能 2.跟前台JS配合方便 3.NodeJS便于前端学习 https://nodejs.org/en/ 1.切换盘符 ...
- nginx的跨域设置
官方文档 中说,只有当响应状态码为以下几种类型中之一时,add_header 才会生效.如果需要 add_header 在所有情况下都生效,可以在后面加上 always 参数即可解决. Adds th ...
- local模式运行spark-shell时报错 java.lang.IllegalArgumentException: Error while instantiating 'org.apache.spark.sql.hive.HiveSessionState':
先前在local模式下,什么都不做修改直接运行./spark-shell 运行什么问题都没有,然后配置过在HADOOP yarn上运行,之后再在local模式下运行出现以下错误: java.lang. ...
- 下面的代码在Python2中的输出是什么?解释你的答案
python2 def div1(x,y): print "%s/%s = %s" % (x, y, x/y) def div2(x,y): print "%s//%s ...
- bzoj2406 矩阵
我们不妨想一想,这道题目又有\(abs\)又有\(Max\)不是很好算对吧. 所以我们二分答案,考虑怎么\(check\). 对于一个点,显然它能够取的范围是\([l,r]\),接着是对于一行一列都有 ...