1.键值设计
1.1 优雅的key设计
- 遵循基本格式:【业务名称】:【数据名】:【id】
- 长度不超过44字节(Redis版本4.0以后)
- 不包含特殊符号
例如:注册业务,保存用户信息的key设计:register:user:12345
为什么使用长度不超过44字节?
因为key是string类型,底层编码包括int、embstr和raw三种,embstr在小于44字节使用,采用连续内存空间,内存占用更小
注意:如果redis版本低于4.0,则embstr在小于39个字节使用
1.2 BigKey
BigKey通常是Key单点大小和Key中成员的数量来综合判定,例如:
- Key本身数据量过大:一个String类型的Key,它的值为5 MB
- Key中的成员数过多:一个ZSET类型的Key,它的成员的数量为10,000个
- Key中的成员的数据量过大:一个Hash类型的Key,虽然只有100个成员数量,但是这些成员数量的Value大小有100MB
推荐值:
- 单个Key的value小于10KB
- 对于集合类型的Key,建议元素数量小于1000
如果发现BigKey:
- redis-cli --bigkeys:利用redis-cli提供的--bigkeys参数,可以遍历分析所有key,并返回key的整体统计信息和每个数据的Top1的big key
- scan扫描:通过自己编程,利用scan扫描Redis中的所有key,利用strlen、hlen、llen、scard、zcard命令判断key的长度(此处不建议使用MEMORY USAGE)
- 第三方工具:如使用Redis-Rdb-Tools分析RDB快照文件,全面分析内存使用情况
- 网络监控:自定义工具,监控进出Redis的网络数据,超出预警值时主动告警
如何删除BigKey:
BigKey内存占用较多,删除这样的key 需要耗费很长的时间,导致Redis主线程阻塞,引起一系列的问题。
- Redis 3.0以及以下版本:如果是集合类型,通过遍历BigKey的元素,逐个删除子元素,最后删除BigKey
- Redis 4.0以后:Redis在4.0后提供了异步删除的命令:unlink
1.3 hash数据类型
如果有hash类型的Key,其中1000万对field和value,field是自增的id,这个key存在什么问题?如果优化?
可以拆分小的hash,将 id / 100作为key,将 id % 100 作为field,这样每100个元素作为一个Hash
2. 批处理优化
2.1 Pipeline
N条命令依次执行,那么N次命令响应的时间 = N次往返的网络传输耗时 + N次Redis执行命令耗时
如果将大量的数据量依次执行插入数据将会是巨大的耗时
Redis中提供了很多Mxxx这样的命令,可以实现批量插入数据:
- mset
- hmset
不要在一次批处理中传输过多的命令,否则单次命令占用宽带过多,会导致网络阻塞
2.2 集群下的批处理:
如MSET和Pipeline这样的批处理需要在一次请求中携带多条命令,如果Redis是一个集群,那批处理命令的多个key必须放在一个插槽中,否则会导致执行失败。
串行命令:使用for循环遍历,依次执行每个命令,实现简单,耗时久
串行slot:在客户端计算每个key的slot,将slot一致分为一组,每组都利用Pipeline批处理,串行执行各组命令,耗时较短,实现复杂
并行slot:在客户端计算每个key的slot,将slot一致分为一组,每组都利用Pipeline批处理,并行执行各组命令,耗时非常短,实现复杂
hash_tag:将所有key设置相同的hash_tag,所有的key的slot一定相同,耗时非常短,实现简单,容易出现数据倾斜
3. 服务端优化
3.1 持久化配置
3.2 慢查询
3.3 命令及安全配置
3.4内存配置
当Redis内存不足时,可能导致Key频繁被删除,响应时间长,QPS不稳定等问题,当内存的使用率达到90%以上的时就需要我们警惕,并快速定位内存占用问题。
- 数据内存:是Redis的最主要的部分,存储Redis的键值信息,主要问题是BigKey问题,内存碎片问题。
- 进程内存:Redis主进程本身运行需要占用一定的内存,如代码、常量池等,这部分的内存大约几兆,大多数生产环境中与Redis数据占用单点内存相比可以忽略。
- 缓冲区内存:一般包括客户端缓冲区,AOF缓冲区,复制缓冲区等,客户端缓冲区又包括输入缓冲区和输出缓冲区,这部分内存占用波动较大,不当使用BigKey,可能会导致内存溢出。
Redis查看内存分配状态:
info memory:命令将仅返回与内存消耗相关的信息
memory status:
内存缓冲区的三种:
- 复制缓冲区:主从复制的repl_backlog_buf,如果大小可能导致频繁的全量复制,影响性能,通过repl-backlog-size来设置,默认1mb
- AOF缓冲区:AOF刷盘之前的缓冲区域,AOF执行rewrite的缓冲区,无法设置容器上限。
- 客户端缓冲区:分为输入缓冲区和输出缓冲区,输入缓冲区最大1G且不能设置,输入缓冲区可以设置。
4. Redis集群最佳实践
在Redis的默认配置中,如果发现任意一个插槽不可用,整个集群都会停止对外服务。
为了保证高可用特性,建议将cluster-require-full-coverage配置设置为false