Redis管道技术使用总结:

Redis服务是一种C/S模型,提供请求-响应式协议的TCP服务,所以当客户端请求发出,服务端处理并返回结果到客户端,一般是以阻塞形式等待服务端的响应,但这在批量处理连接时延迟问题比较严重,所以Redis为了提升或弥补这个问题,引入了管道技术:可以做到服务端未及时响应的时候,客户端也可以继续发送命令请求,做到客户端和服务端互不干涉影响,服务端并最终返回所有服务端的响应,这在促进原有C/S模型交互的响应速度上有了质的提高。


1、特点

在C/S交互中,客户端可发送任意数请求命令,不需要等服务端响应后再行发送请求;而服务端可以一次性完成并返回所有客户端请求结果,也可以分批次返回请求结果,这主要看服务端处理结果的速度而定。

 

2、语法

在构建批量命令集或是组装属性字符串时,命令间使用\r\n进行分离即可,例如:

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

 

3、验证

A、开启redis服务

$/redis/bin/redis-server  /redis/etc/redis.conf

 

B、测试是否可用

$(echo -en "PING\r\n SET test redis\r\nGET test\r\nINCR visit\r\nINCR visit\r\nINCRvisit\r\n"; sleep 10) | nc localhost 6379

 

结果:

Java redis 管道优化 redis管道技术_Java redis 管道优化

 

NOTE:

使用PONG命令测试本地服务使用连通;

使用SET/GET赋值和取值;

使用INCR三次为visit加1;

 

4、使用

这里举个实际使用例子:同步数据库数据到Redis缓存数据库,目的是为提高速度降低数据库的IO操作频次,以及降低服务器的压力,也就是我们常说的使用Redis缓存数据库需求(这里我们以Mysql数据库为例说明)。

A、新建t_user_info数据表

Java redis 管道优化 redis管道技术_Redis_02

 

B、编写一转换json的lua

因为Redis 2.6已开始lua的解析支持,所以我们可以使用它来在倒入数据到Redis数据库过程中,实时转换从数据库读取的数据格式为json,这样方便后期程序拿到数据之后不需要再行编码解析直接使用即可(至于lua,这里不介绍,以避免偏离主题,后续博文会专门介绍它的使用细节),lua脚本内容如下:

for k,y 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));  

 

NOTE:

这里不介绍lua的相关内容,具体会在后续文章中介绍,请留意关注博客更新。

 

C、Redis与Mysql数据同步

首先,编写一个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' AS redis_cmd,CONCAT(account,password,'_hash') AS redis_key,

'id' AS id_key,id AS id_val,

'account' AS account_key,account AS account_val,

'password' AS password_key,password AS password_val,

'nickname' AS nickname_key,nickname AS nickname_val,

'email' AS email_key,email AS email_val,

'address' AS address_key,address AS address_val

FROM t_user_info

) AS t

 

其次,执行同步操作指令:

$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

 

最后,查看同步是否正常:

Java redis 管道优化 redis管道技术_redis_03

 

D、结果查看

$/redis/bin/redis-cli -p 6379

127.0.0.1:6379>hgetall cwteame10adc3949ba59abbe56e057f20f883e_hash

由上图已经说明,我们的数据同步正常,而且在Redis中每个key对应了数据库中的一条记录,所以这个可以在高用户量时,缓存用户数据提高登录速度。

 

 

NOTE:

cwteame10adc3949ba59abbe56e057f20f883e_hash:

代表key为account+password+_hash组合的键名字;

 

5、注意

A、同步Mysql数据到Redis中缓存

需要保证Redis中的数据与Mysql中一致,虽然不一致的时候会从数据库中获得,但是就浪费了Redis的资源优势。

建议:使用定时机制,定期同步数据;

 

B、Mysql数据在Redis中结构关系

Redis是非关系行数据存储结构,所以需要建立Mysql中的多个关联表到Redis中的存储结构关系规则,目的只为方便找到关联数据内容。