业务场景:Redis 做为目前主流的key-value 内存数据库,由于其高并发,存储查询速率快,咱们不少的热点数据均会存储到Redis 中,若是数据量较大的话,昂贵的内存消耗也是一笔很大的支出,所以Redis 内存优化是颇有必要的。
上图能够看到:Redis内部的对象数高达:1,599,098,020(15亿),其内存使用高达 371G ,而且持续的增多,须要咱们尽快优化,释放多余的空间。
{ "expireTime": "253402271999000", "value": "test_test_test_test" }
主要内存优化依据是:
Redis 内部Hash 数据结构的编码方式主要有两种:java
- OBJ_ENCODING_ZIPLIST(压缩列表)
- OBJ_ENCODING_HT(哈希表)
Redis 内部会根据数量的状况自适应的选择这两种编码方式中 最优 的一种,这种操做彻底对用户透明,选择压缩列表存储的依据主要是:linux
- 数据条目较少(hash-max-ziplist-entries)即 Hash 的filed 较少 field 个数 默认小于 512
- 数据值较少(hash-max-ziplist-value)即Hash的value 值较少 value 值的长度小于64
即默认存储为压缩列表存储的条件为git
field_num < hash-max-ziplist-entries && value.length < hash-max-ziplist-value综上所述:根据前面看到的业务场景,彻底知足此种场景,这是选择由string存储变为 Hash存储的一个缘由github
OBJ_ENCODING_ZIPLIST 编码的主要思想是:空间换时间,适应于字段个数比较少,字段值也比较小的场景。
为了全方位的对内存进行优化,那么key 以及 hash 的field 进行必要的压缩redis
- 若是是字符串的话能够进行分段优化,针对数据进行16进制转换
- 字符串使用简写方式
为保证测试的准确性,私有服务器安装Redis 进行优化前与优化后内存空间测试
如下为整个测试过程:docker
- docker 安装 Redis
docker pull redis
docker ps # 查询当前容器
docker exec -it ****** /bin/bash # 进入容器内部 redis-cli -a 123456 #打开Redis-cli链接Redis info memory # 查询安装完成后Redis 的内存使用状况
以上为Redis 服务搭建过程的简单记录数据库
- 数据存储测试(未优化前)
优化前 存储 1000000 string 类型数据以下:json
-- string key 0:1:201155:100:545953888100 -- string value { "value": "3.6230093077568726-0.3630194103106919100", "expireTime": "2147483647" }
由上图内存存储可知:未优化前 1000000 条 string 消耗内存:200.12M
执行完测试,将此前存入的数据删除bash
(1)数据存储测试(优化key value)服务器
- 压缩key的长度:将最后的无业务标识的字符串转换为:16进制
- 压缩value 的长度:压缩value的数据
优化后 存储1000000数据使用内存:139.10M 相比较优化前优化内存:30%
偷偷窃喜下,若是进行这次优化:节省内存:115G
(2)数据存储测试(优化key value)
- 压缩key的长度:将最后的无业务标识的字符串转换为:64 进制
- 压缩value 的长度:压缩value的数据
这次优化变化不明显,仅仅下降了 不到1M ,疑惑脸。。。
因而乎对于key的长度不进行压缩,只对value值进行压缩进行测试结果以下:
由以上测试可得:1000000数据,内存使用率为 146.59M ,故此 16/64 进制对key的压缩影响并不明显。
(3)数据存储测试(优化key value)
- 压缩key的长度:将最后的无业务标识的字符串转换为:64 进制
- 压缩value 的长度:压缩value的数据,不在存储json,只存储,attr1:value,attr2:value2
以上优化后,存储1000000数据使用内存:123.86M,优化达到:38%
(4)数据存储测试(优化key value)
- 压缩key的长度:将最后的无业务标识的字符串转换为:64 进制
- 压缩value 的长度:压缩value的数据,不在存储json,只存储,attr1:value
通过第4次进行优化,内存的占用依旧与第三次相差很小,可是仍然在减小,这次内存占用为 123.71M,继续对value值作压缩
(5)数据存储测试(优化key value)
- 压缩key的长度:将最后的无业务标识的字符串转换为:64 进制
- 压缩value 的长度:压缩value的数据,只存储,attr1:value, exp(过时时间戳)压缩为64进制
通过第5次进行优化,内存占用达到了 116.27M ,优化达到:42%
- 数据存储测试(优化key value的基础上进行 数据结构变动:变动为HASH)
见证奇迹的时刻到了,变动HASH 结构后,1000000数据内存占用 100.49M,优化50%
思考:
Redis 的内存优化,须要配合业务场景进行针对性的优化,并非一味的已减小内存为主要的优化目标,咱们也应该在空间和时间上找到一个平衡点进行恰当的优化,就那这次优化来讲,虽然内存减小了 50% ,可是在实际应用中考虑到,该数据对于效率要求比较高,因此在进行编码解码过程当中也存在时间的消耗,最终并非采用内存优化度最大的那种方案。
这次测试的代码都可在github 传送门: 项目测试