根据服务redis响应p99不符合理想,根据redis server端的监控指标发现在系统调用期间出现的超100ms的查询不是由于slowlog导致
1.查看两台机器之间的延时,一个RT延时不超过0.15ms
2.查看redis server,在server端设置5ms的延时监控,目前为止也是没有采集到的对应延时时间大的时候的指标
config set latency-monitor-threshold 5
3.根据lettuce共享连接的原理来查看代码实现,发现mget在跨slot的时候会经历:1拆分 → 2发送 → 3合并
查看了redis cluster 4的官方文档,发现rediscluster4的mget是不支持跨slot的
|
那么算的话根据原理,时间应该等于:分发耗时+多个server耗时+多个网络RT+合并耗时
复杂度分析:
get复杂度O(n)
mget复杂度O(slot.size)
1.首先想lettuce作者怎么面对大家的质疑:
https://gitter.im/lettuce-io/Lobby?at=5bb3bf946e5a401c2d081872
mp911de的回答:
Is there anyway to optimize this ?
@mp911de
Yes: Don't use cross-slot keys.
Everything else requires split/merge/sort to issue multiple commands and correlate the responses back in order.
We probably could add size initializers to allocate maps and lists at the expected size to prevent reallocations.
For a batch get from multiple slots is there any better approach ?
@mp911de
Have you tried using the individual connections that serve the hash slot and dispatching commands in your own code?(意思是让提问者尝试hashtag,这样就到一个slot里了)
这个是来自github的答疑:Question about Redis MGET with Lettuce Client(意思是将大批量的任务拆分成多次的小批量,从server端思考尽可能不要影响其他客户端的请求)
这个mget的量也从其他地方得到验证当一次batch大于1000性能急剧下降:
2.其他尝试
#既然lettuce不行,那咱们抛弃名媛找新欢jedis呢?发现已经有人帮助踩坑了
https://www.jianshu.com/p/f2681aa319a3
来自中国用户的测评:意思是jedis会在mget的时候遇见同样的跨分区问题,jedis采用的是循环sleep 10ms查看数据有没有到达,后面作者使用线程池get
#那么lettuce有没有优化的空间呢?发现也有人踩过坑了
https://blog.csdn.net/qq_31665011/article/details/100737095
来自中国用户的测评:意思是codis会在mget的时候根据shard进行pipeline请求,lettuce是按照slot进行mget请求(so,要去改源码?单纯了为了快,我觉得作者是不能接收的 作者的目的是实现mget功能,并不是用pipeline混淆mget概念)
复杂度分析:
pipeline技术下的mget复杂度O(node.size)
#那么pipeline一定比mget快吗?
StackOverflow上的总结是:慢的根源在于编解码器,这个还没有求证毕竟是别人的结论
另外在lettuce共享连接这个文章,我们强调过pipeline源码问题,建议pipeline使用按照官方文档
也有人抓包看过,文章如下:
Spring Data Redis与Lettuce 使用 pipeline 时注意事项
|
1.lettuce的mget是根据slot多次发送的
2.可以尝试把要mget的keys通过hashtag放到一个slot
3.可以尝试根据shard然后pipeline获取(建议量50~1000)
4.减小mget的batch量(建议量小于100),多批次根据业务处理
mget性能测试脚本:./redis-mget.sh 1000
1.set数据
redis-set-1024.sh
|
2.根据传入参数mget压测
redis-mget.sh
|