Redis 集群下mget优化


1 背景
Redis是知名的、应用广泛的NoSQL数据库。但是在集群环境下,我们发现mget的效率实在过低,很多时候甚至还不如for循环进行get、set。

2 分析原因
2.1 现象
业务在从Codis迁移到Redis Cluster的过程中,在Redis Cluster和Codis双写了相同的数据。结果Codis在比Redis Cluster多一次连接proxy节点的耗时下,同样是mget获取相同的数据,使用Lettuce访问Redis Cluster还是比使用Jeds访问Codis耗时要高,于是我们开始定位性能差异的原因。

2.2 定位问题
2.2.1 Redis Cluster的架构设计
导致Redis Cluster的mget性能不佳的根本原因,是Redis Cluster在架构上的设计导致的。Redis Cluster基于smart client和无中心的设计,按照槽位将数据存储在不同的节点上

如上图所示,每个主节点管理不同部分的槽位,并且下面挂了多个从节点。槽位是Redis Cluster管理数据的基本单位,集群的伸缩就是槽和数据在节点之间的移动。

通过CRC16(key) % 16384 来计算key属于哪个槽位和哪个Redis节点。而且Redis Cluster的Multi-Key操作受槽位限制,例如我们执行mget,获取不同槽位的数据,是限制执行的:

2.2.2 Lettuce的mget实现方式
lettuce对Multi-Key进行了支持,当我们调用mget方法,涉及跨槽位时,Lettuce对mget进行了拆分执行和结果合并,代码如下:
mget涉及多个key的时候,主要有三个步骤:

1、按照槽位 将key进行拆分;

2、分别对相同槽位的key去对应的槽位mget获取数据;

3、将所有执行的结果按照传参的key顺序排序返回。

所以Lettuce客户端,执行mget获取跨槽位的数据,是通过槽位分发执行mget,并合并结果实现的。而Lettuce基于Netty的NIO框架实现,发送命令不会阻塞IO,但是处理请求是单连接串行发送命令:

所以Lettuce的mget的key数量越多,涉及的槽位数量越多,性能就会越差。Codis也是拆分执行mget,不过是并发发送命令,并使用pipeline提高性能,进而减少了网络的开销。

3 解决

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值