redis缓存mysql技术实现原理_Redis缓存Mysql技术实现

Redis缓存Mysql技术实现:

Redis缓存的相关内容这里不介绍,具体可参考博文《专题之Redis缓存分析及使用》。这里着重介绍下Redis如何缓存Mysql数据的IO压力,做到可观的性能提升目的。在实际的业务需求下,随着企业数据量的不断递增,访问数据库的IO频率大大提升,即使Mysql做了相关的优化,但也不能满足需求,时而等待许久服务端才会响应(技术讨论群:489451956(新))。

这里就以用户登录为例进行说明(只实现后台部分,使用Redis前提是用户量已经达到百万级,否则有点大才小用)。首先从Redis中查询(为了提高访问响应速度),前提是Mysql中的数据已经同步到Redis中,如果Redis中已经存在该用户,那么就直接从其中获取并返回,否则再从Mysql中读取。这是一个简单的缓存技术例子,也是Redis使用的开始,后续我会在这个例子中继续优化处理细节,因为目的只有一个:就是提供服务端性能和用户体验。

一、数据表构建

新建一张t_user_info数据表:

0818b9ca8b590ca3270a3433284dd417.png

二、Redis与Mysql数据同步

同步Mysql数据到Redis中:

1、数据表插入200万条数据(存储过程)

2、同步数据到Redis中

在这里使用了Redis的管道技术,目的是提高Redis的服务性能。

A、首先,准备编写一个.sql脚本

SELECT CONCAT(

'*14\r\n',

'$',LENGTH(redis_cmd),'\r\n',redis_cmd,'\r\n',

'$',LENGTH(redis_key),'\r\n',redis_key,'\r\n',

'$',LENGTH(id_key),'\r\n',id_key,'\r\n','$',LENGTH(id_val),'\r\n',id_val,'\r\n',

'$',LENGTH(account_key),'\r\n',account_key,'\r\n','$',LENGTH(account_val),'\r\n',account_val,'\r\n',

'$',LENGTH(password_key),'\r\n',password_key,'\r\n','$',LENGTH(password_val),'\r\n',password_val,'\r\n',

'$',LENGTH(nickname_key),'\r\n',nickname_key,'\r\n','$',LENGTH(nickname_val),'\r\n',nickname_val,'\r\n',

'$',LENGTH(email_key),'\r\n',email_key,'\r\n','$',LENGTH(email_val),'\r\n',email_val,'\r\n',

'$',LENGTH(address_key),'\r\n',address_key,'\r\n','$',LENGTH(address_val),'\r\n',address_val,'\r'

)

FROM(

SELECT

'HMSET' ASredis_cmd,CONCAT(account,password,'_hash') AS redis_key,

'id' AS id_key,id AS id_val,

'account' AS account_key,account ASaccount_val,

'password' AS password_key,password ASpassword_val,

'nickname' AS nickname_key,nickname ASnickname_val,

'email' AS email_key,email AS email_val,

'address' AS address_key,address ASaddress_val

FROM t_user_info

) AS t

B、其次,编写个redis的table到json的lua

Redis2.6版本以后开始支持内嵌了lua环境,支持使用lua解释器执行脚本:

for k,v in pairs(ok) do

for key,val in pairs(v) do

if key%2 == 0 then

tmp[v[key-1]] = v[key];

end

end

ret[k]=tmp;

end

ngx.say(cjson.encode(ret));

C、最后,执行数据同步命令

$ mysql -h 127.0.0.1 -uroot-Dcwteam --skip-column-names --raw < /redis/sql/mysql_to_redis.sql |redis-cli --eval /redis/lua/redis_table_json.lua --pipe

结果:

0818b9ca8b590ca3270a3433284dd417.png

看到上图,说明我们已经导入成功了,速度真够快的,只用了30秒左右。

三、Redis缓存Mysql

Redis缓存Mysql的实现比较简单,在文章的叙述部分已经说明,这里不再赘述。这部分主要介绍的内容是介绍如何从Redis和mysql中获取数据,如何缓存Mysql的基本实现,因为前面已经做好了Redis和Mysql之间的数据格式协议,并在同步的时候,就将redis的Hash做好了对应关系,并转化为json格式,具体的实现请参看下面:

1、Php代码实现:

//使用Redis缓存Mysql

public functionredisCacheMysql() {

header("Content-Type:text/html;charset=utf-8");

$uRedis= new\Redis();

$uRedis->connect('127.0.0.1',6379);

//前端获得的账号信息(这只是演示例子,也只是一种方式)

$account= 'cwteam';

$password= 'e10adc3949ba59abbe56e057f20f883e';

$result= '';

$userKey= $account.$password.'_hash';

//先从Redis中取,如果没有就去请求mysql

if(!$uRedis->exists($userKey)) {

//不存在读取数据库

$where= array();

$where['account'] = $account;

$where['password'] = $password;

$user= D('UserInfo')->where($where)->find();

if($user) {

$result.= json_encode($user).'';

}else{

$result.= '结果:该用户不存在!';

}

$result.= '我从mysql中读取的!';

} else{

//存在就从redis中取

$user= $uRedis->hGetAll($userKey);

if($user) {

$result.= json_encode($user).'';

}else{

$result.= '结果:该用户不存在!';

}

$result.= '我从Redis中读取的!';

}

echo'结果:'.$result .= '';

}

2、结果验证

Redis无缓存时:

此时,我们可以在mysql中新增一条Redis中未缓存的记录,然后执行:

0818b9ca8b590ca3270a3433284dd417.png

Redis有缓存时:

0818b9ca8b590ca3270a3433284dd417.png

注意:

使用Redis缓存Mysql的实现是很有必要的,当实际数据量很大并且请求频次很高的时候,Redis就凸显出了它的优势所在,这样做的目的有:a、减轻数据库IO的压力,b、提高用户请求响应的速度。

好了,文章中不免会有遗漏的地方,欢迎在顶部的Q群或下面的讨论中交流。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值