Redis不同版本性能研究

发布时间 2023-12-22 10:11:14作者: 济南小老虎

Redis不同版本性能研究


背景

前期同事遇到了一个大key的慢查询.
前提条件是: 一个 60万key的环境里面. 
有一个 260万元素的set类型的key

产品经常会进行 smember key 的操作
出现了长达1.5秒的 slowlog. 
同期还出现了内存飙涨与实际内存使用不符的情况. 

所以想着研究一下内存. 

发现新问题

当时与同事一起看时 记得 slowlog 是 1.5秒左右

因为我手头上刚好有一个 redis6.2.6 的飞腾ARM版本的环境,就直接拿来用了.
当时只是定位到了问题,所以每天关注.
早上起来,我突发奇想,是不是smember 导致内存上升, 然后就在ARM的环境里面执行了相关的命令
发现slowlog: 
slowlog get
 1) 1) (integer) 18
    2) (integer) 1703203780
    3) (integer) 854102
    4) 1) "SMEMBERS"
       2) "ecp:counter:*

发现只有0.85秒左右的延迟 我感觉不太对, 理论上ARM会更慢才对? 为何会这样? 
同期发现内存是没有啥变化的.  所以没有解决旧问题, 但是发现了新问题
Redis的版本信息为: 
redis_version:6.2.8
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:1274cf00783b476
redis_mode:standalone
os:Linux 4.19.90-24.4.v2101.ky10.aarch64 aarch64
arch_bits:64

思考

Redis是单线程的
理论上他的延时只跟CPU的工作能力相关 
理论上不应该出现如此大的差异. ARM 的延时只有 x86的一半
这个简直是不可理解的.
突然先到 客户现场使用的是redis 4.0.11 的版本. 
然后进一步想到是不是版本性能差异? 
想干就干一把

下载不同版本的redis

http://download.redis.io/releases/

redis-4.0.11.tar.gz                                27-Jun-2020 15:51             1739656
redis-5.0.0.tar.gz                                 27-Jun-2020 15:51             1947721
# 发现发布时间不准. 尴尬
Redis 1.0 是 Redis 数据库的第一个正式版本,于2009年3月发布。
Redis 2.0 于2010年4月发布。Redis 2.0 引入了一些重要的新特性,如虚拟内存机制、实现 Redis 的 Lua 脚本语言、支持哈希类型的直接操作以及提供慢查询日志等功能
Redis 2.6 于2012年8月发布。Redis 2.6 引入了一些重要的新特性,如虚拟内存、持久化和内存优化等。
Redis 2.8 于2014年4月发布。Redis 2.8 引入了一些重要的新特性,如对 Lua 脚本、集群和二进制流支持的提升
Redis 3.0 于2015年4月发布。Redis 3.0 引入了一些重要的新特性,如更加高效和可靠的集群方案、更加安全和可靠的持久化机制,以及增强了对 Lua 脚本、哈希表和流数据的支持。
Redis 4.0 于2017年9月发布。Redis 4.0 引入了一些重要的新特性,如更加强大和高效的集群功能、更加安全和可靠的持久化机制、新的数据类型、事务和流水线批处理等功能。
Redis 5.0 于2018年10月发布。Redis 5.0 引入了一些重要的新特性,如更加强大和高效的模块化架构,更加安全和可靠的持久化机制、新的数据类型、多种集群模式、新增命令等等。
Redis 6.0 是 Redis 数据库的一个重要版本,于2020年4月发布, 支持了IO多线程
Redis 7.0 在2022年4月27日正式发布 它不仅包含了50多个新命令,还有大量核心新特性与改进
Redis 7.2 于2023年8月15日发布. 

关于redis版本号的说明

Redis 使用标准版本标记进行版本控制:major.minor.patchlevel。
偶数的版本号表示稳定的版本, 例如 1.2,2.0,2.2,2.4,2.6,2.8。
奇数的版本号用来表示非标准版本,例如2.9.x是非稳定版本,它的稳定版本是3.0。

测试规划

计划编译 4.0.11 和 7.2.3 等版本进行验证. 
导入dump文件, 执行smember 命令查看slowlog的结果信息

编译时间:
4.0.11
real    1m43.809s
user    1m39.276s
sys     0m6.801s

5.0.14
real    2m54.587s
user    2m49.529s
sys     0m9.701s

7.2.3
real    5m4.991s
user    4m55.361s
sys     0m16.131s

注意都是 飞腾S2500 的服务器
可以看到编译时间 4.0.11 100秒.  7.2.3 编译时间 304秒. 
经过六年时间的发展, redis的代码量可能有了2-3倍的变化. 

所以东西变重是很正常的. 

时间差异

Redis 4.0.11
slowlog get
1) 1) (integer) 0
   2) (integer) 1703205853
   3) (integer) 1061550
   4) 1) "smembers"
      2) "ecp:counter:
列表完整展示时间: (124.69s)
used_memory:2176292832
used_memory_human:2.03G
used_memory_rss:2368798720
used_memory_rss_human:2.21G
 dbsize
(integer) 648463

Redis 5.0.14 
1) 1) (integer) 3
   2) (integer) 1703208791
   3) (integer) 1019090
   4) 1) "SMEMBERS"
      2) "ecp:counter:
used_memory:2175424280
used_memory_human:2.03G
used_memory_rss:2210332672
used_memory_rss_human:2.06G
dbsize
(integer) 648463


Redis 6.2.8 
1) 1) (integer) 18
    2) (integer) 1703203780
    3) (integer) 854102
    4) 1) "SMEMBERS"
       2) "ecp:counter
列表完整展示时间: (112.00s)
内存使用情况:
used_memory:2175438112
used_memory_human:2.03G
used_memory_rss:2255749120
used_memory_rss_human:2.10G
 dbsize
(integer) 648463

Redis 7.2.3 
这个版本的dump文件数据格式发生了变化, 无法加载. 
SMEMBERS ecp:counter
(empty array)
这一点非常坑. 
used_memory:1584538448
used_memory_human:1.48G
used_memory_rss:1626537984
used_memory_rss_human:1.51G
used_memory_peak:1584791080
used_memory_peak_human:1.48G
dbsize
(integer) 648463


一个简单结论

1. Redis 6.2.8 导出的文件 4.0.11 无法加载,提示版本不对, 无法加载文件类型为 9的 内存文件.
2. Redis 6.2.8 和 redis 4.0.11 的dump文件时可以向前兼容的, 能够加载里面的大部分数据. 
3. Redis 7.0.11 可以加载 4.0.11和 6.2.8 导出的dump文件, disize也是准确的, 但是缺少了部分数据
   Set类型的key出现了数据丢失, 是一个不兼容升级. 
4. 简单看到 Redis6.2.8 比 Redis 4.0.11 的最大时间有了一定的优化. 
   比较三次的slowlog的时间为:
   redis 4.0.11 的三次平均时间: 1,059,415
   redis 5.0.14 的三次平均时间: 1,023,054
   redis 6.2.8  的三次平均时间: 842,629

发现redis的确随着版本的提升, 性能出现了一定程度的提高. 

客户现场使用的是x86的redis 但是因为采用的是 K8S pod运行, 并且采用了 nfs存储. 
我怀疑K8S容器化的损耗也比较大, 对性能的影响也比较多. 
客户理论上应该是2020年左右的服务器, 理论上比 飞腾S2500至少要领先 5年. 

所以现在推断 一方面是版本太低, 一方面是容器化损耗导致性能下降. 

如果对性能要求比较高, 一方面使用高频CPU, 一方面使用更新的性能更好的版本, 一方面降低部署复杂度,让软件更接近于硬件
性能会更加好一些.