Redis内置命令
通过Redis内置命令对目标Key进行分析,可以使用风险较低的命令来查询目前Key的字节数、列表长度或成员数量
STRING类型:执行STRLEN命令,返回对应Key的value的字节数。
LIST类型:执行LLEN命令,返回对应Key的列表长度。
HASH类型:执行HLEN命令,返回对应Key的成员数量。
SET类型:执行SCARD命令,返回对应Key的成员数量。
ZSET类型:执行ZCARD命令,返回对应Key的成员数量。
STREAM类型:执行XLEN命令,返回对应Key的成员数量。
注意!!!
DEBUG OBJECT
与MEMORY USAGE
命令在执行时需占用较多资源,且时间复杂度为O(N)
,有阻塞Redis实例的风险,不建议使用。
大Key优化
业务侧 -- 根本
业务侧优先考虑避免大key设计,不要什么都往里放,仅仅缓存必要的数据字段
拆分 分片
例如将含有数万成员的一个HASH Key拆分为多个HASH Key,并保证每个Key的成员数量在合理范围。在Redis集群架构中,拆分大Key能对数据分片间的内存平衡起到显著作用
需要考虑下面几个问题:
定量拆分还是动态拆分?定量拆分需要考虑value增长的问题;动态分片就是先按原key读第一个分片,第一个分片的value记录分片的总数,然后再按照shard_num取。
存在部分写问题,比如写入10个分片的数据,只有5个分片写入成功,就会造成数据不一致问题。解决方案有下面几个
引入版本机制
value最前面带上版本号
一个分片不对就算错误,重新加载,容易陷入死循环
开发、维护、组装的成本
更换存储方案
换别的没有大key问题的存储
持久型kv存储
软件:LSM-Tree
硬件:固态存储
本地缓存,和redis结合实现多级缓存
CDN
数据压缩
golang自带的zip和unzip可以对string类型的数据进行压缩
string类型
考虑使用容器型数据结构替换 string,提高内存利用效率,也能一定程度节省键名空间
合理的清理机制
对过期数据进行定期清理
堆积大量过期数据会造成大Key的产生,例如在HASH数据类型中以增量的形式不断写入大量数据而忽略了数据的时效性。可以通过定时任务的方式对失效数据进行清理。
在清理HASH数据时,建议通过HSCAN命令配合HDEL命令对失效数据进行清理,避免清理大量数据造成Redis阻塞。
对大Key进行清理
直接删除的话容易阻塞,因为Redis是单线程,从而影响到其他线上请求,超时增加的话会导致Redis连接打满,从而引发各种异常问题
解决方案:
选择业务流量低峰期的时候删除
分批定时定量删除:一次删除一部分,防止一次性删除大量数据导致阻塞
hash:hsacn扫描
set:srandmember 随机取数删除
zset:zremrangebyrank 移除指定排名(rank)区间内的所有元素
list:直接 pop 删
异步删除:用unlink代码del删除,只是将键与键空间断开连接,实际的删除异步进行,非阻塞,逐步清理