Redis开发规范解析(一)--键名设计

vincent0809
发布于 2022-4-16 12:15
浏览
0收藏

去年我写过一个《阿里云Redis开发规范》,在网上转载很多,但其实说心里话,我并不认为写的多好,受制一些客观因素和篇幅,有些不够细致和深入,所以想在公众号里详细解析下,希望对大家有帮助。

 

本篇是第一篇:由键名设计想到的SDS内存优化

 

原文


1. key名设计


 ◆(1)【建议】: 可读性和可管理性


以业务名(或数据库名)为前缀(防止key冲突),用冒号分隔,比如业务名:表名:id

Redis开发规范解析(一)--键名设计-鸿蒙开发者社区 ◆(2)【建议】:简洁性


保证语义的前提下,控制key的长度,当key较多时,内存占用也不容忽视,例如:

Redis开发规范解析(一)--键名设计-鸿蒙开发者社区

 ◆(3)【强制】:不要包含特殊字符


反例:包含空格、换行、单双引号以及其他转义字符

 

解析


上面这些内容本来没什么好说的,但是这个就和做菜“放盐少许”一样,key多长才算最佳呢?我们从之前遇到的一个问题讨论下。

 

一. 1个问题


之前公司有个同事找我,说他申请两个集群,双写两个集群,但是写满后容量是这样的:

Redis开发规范解析(一)--键名设计-鸿蒙开发者社区遇到此类问题,我还是习惯把老图翻出来:

Redis开发规范解析(一)--键名设计-鸿蒙开发者社区

此类问题有很多种可能:

 

◆自身内存:没多少,几百KB
◆Lua内存:没用
◆缓冲内存:AOF和复制缓冲配置一致,客户端缓冲不存在,客户端已经停了。
◆对象内存:
◆键值个数:个数相同
◆内部编码:都是字符串类型,而且ziplist,quicklist等配置一致

 

那么问题出现在哪里呢?比较好的是,我们这边Redis的集群ID有一定含义的,比如12xxx开头的是Redis 3.0.x,以13xxx开头的是Redis 3.2.x,以14xxxx开头的是Redis 4.0.x

Redis开发规范解析(一)--键名设计-鸿蒙开发者社区这时候想到是了可能是SDS的问题,Redis 3.2开始SDS有个升级,https://raw.githubusercontent.com/antirez/redis/3.2/00-RELEASENOTES

Redis开发规范解析(一)--键名设计-鸿蒙开发者社区二、一个实验


我做了一个简单试验,分别在Redis 3.0.7和Redis 4.0.12,写入10亿个44字节的key和value,代码如下:

Redis开发规范解析(一)--键名设计-鸿蒙开发者社区Redis 3.0.7的内存消耗:

Redis开发规范解析(一)--键名设计-鸿蒙开发者社区Redis 4.0.12的内存消耗:

Redis开发规范解析(一)--键名设计-鸿蒙开发者社区

可以看到Redis 4.0.12的内存消耗比Redis 3.0.7小了30G,几乎可以顶上一台小内存机器了。

 

三. Redis的SDS


下面来看看为什么选的是44字节:

 

    1.内部编码


Redis中的字符串类型,有三种内部编码:raw、embstr、int。当值小于44字节(Redis 3.2+),使用embstr,否则使用raw(这里不讨论int),例如

Redis开发规范解析(一)--键名设计-鸿蒙开发者社区下图展示了两者的区别,可以看到embstr将redisObject和SDS保存在连续的64字节空间内,这样可以只需要一次jemalloc分配,而对于raw来说,SDS和redisObject分离,需要两次jemalloc,而且占用更多的内存空间。

Redis开发规范解析(一)--键名设计-鸿蒙开发者社区Redis开发规范解析(一)--键名设计-鸿蒙开发者社区回头来看内存不一致的问题,实际不存在embstr和raw的区别,因为他们是双写,键值内容应该是完全一致的。那肯定就是SDS的变化:

Redis开发规范解析(一)--键名设计-鸿蒙开发者社区

可以看到embstr在3.2+中使用了叫sdshdr8的结构,在该结构下,元数据只需要3个字节,而Redis需要8个字节,所以总共64个字节,减去redisObject(16字节),再减去SDS的原信息,最后的实际内容就变成了44字节和39字节。

 

现在回过头来屡一下两个问题:

 

1.字符串多短为好:其实就是要尽量使用embstr。

 

2.Redis 3.0 和 Redis 3.2+的sds有很大不同,新版本的sds会根据字符串长度使用不同的原信息,下面来看一下

 

Redis 3.0

Redis开发规范解析(一)--键名设计-鸿蒙开发者社区Redis 3.2+ (3.2 4.0 5.0):sdshdr5、sdshdr8、sdshdr16、sdshdr32、sdshdr64、

Redis开发规范解析(一)--键名设计-鸿蒙开发者社区四、结论


1.SDS在Redis 3.2+有可能节省更多的空间,但3.2更像一个过渡版本,Redis 4更加适合(异步删除、psync2、碎片率整理),我已经在线上大量使用,“赶紧”去用吧。
2.embstr从Redis3 39字节->Redis3.2+ 44字节
3.做个环保的程序员,小优化大效果。

分类
标签
收藏
回复
举报
回复
    相关推荐