存储结构优化
尽量保证单个结构中存储的数据量(这里的数据量即包括散列中的key个数、也包括值大小),不要超过ziplist的临界条件,尽量让Redis使用ziplist短结构来存储。比如当某个Hash结构中的元素在不足一定数量时会被压缩成ziplist存储结构,所以可以大量节约内存。
# 表示当hash表中的条目数小于512条<即键值对数量>
# 且每个value的长度不超过64字节时,就将该hash结构转换成ziplist结构存储。
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
# 当存储个数小于512的时候,并且数据全为整型时 转换成ziplist。
# 否则退化为hash结构。
set-max-intset-entries 512
# 与上面的hash一样,只是这里为zset结构进行设置
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
Key的名称尽量简单明了
原因同下
注意控制Key的数量
随着业务的扩展,存储在Redis中的Key也会越来越多,但考虑到key本身的占用,以及集群模式下维护slot与key的映射关系等原因,key过多的情况下也会造成巨大的浪费(比如上亿)。所以减少key的个数很有必要,通常采用的方案是转Hash结构存储,比如将原来使用Redis String结构存储的多个具有关联的key,转化成Hash结构。
举例:以前有三个key,
set user.stz.id 1,
set user.stz.name zst,
set user.stz.h 180。
上述三个key,有很明显的关系,那么我们就可以将这转成hash结构来存储,这样redis中就只存在一个key:user.stz
hmset user.stz id 1 name stz h 180
如果多个String类型的Key之间无关联,同样也可以放到Hash中,关键在于确定所在hash。比如说将3W个无关联关系的String Key,存到100个hash中,每个hash中存300个,这样就可以减少29900个key。我们只需要确定对某个key存取都会映射到同一个桶就可以了。这种情况下,采用普通hash算法即可实现,比如: hash(key) % 100即可以确定所在桶。
为每个key设置过期时间
这一点基本上无可争议,并且应该尽量错开时间,防止缓存雪崩。针对不同情况设置不同时间,比如说短信校验码这种通常5到10分钟就可以了;排行榜数据可能每小时、每天更新一次;而缓存的一些活动商品,可能会有好几天,甚至跟活动挂勾。
其中一些特殊的情况,比如使用Redis实现分布式锁时,在最后甚至你需要手动删除该key,而不应该仅仅依赖Redis自己的过期策略
注意value的大小
- 单个key存储的value很大:这种情况得根据value的结构来确定方案,比如说value是一种对象的Json化表示,那么可以考虑将转换成Hash进行存储。
- value中存在太多元素:比如说hash结构的值中有过多的key,同样可以考虑拆分,最好经过拆分之后,让单个hash达到转换成ziplist的条件。
修改linux中TCP监听的最大容纳数量
WARNING: The TCP backlog setting of 511 cannot be enforced because
/proc/sys/net/core/somaxconn is set to the lower value of 128.
在高并发环境下你需要一个高backlog值来避免慢客户端连接问题。注意Linux内核默默地将这个值减小到/proc/sys/net/core/somaxconn的值,所以需要确认增大somaxconn和tcp_max_syn_backlog两个值来达到想要的效果。
echo 511 > /proc/sys/net/core/somaxconn
注意:这个参数并不是限制redis的最大链接数。如果想限制redis的最大连接数需要修改maxclients,默认最大连接数为10000
修改linux内核内存分配策略
原因:避免fork子进程时,内存不足,造成redis服务器的down机或者IO负载过高,应将内存分配策略应该设置为 1 ,表示内核允许分配所有的物理内存,而不管当前的内存状态如何
错误日志:WARNING overcommit_memory is set to 0! Background save may fail under low memory condition.
To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or
run the command 'sysctl vm.overcommit_memory=1'
内存分配策略有三个可选值:
-
0: 表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请允许;否则,内存申请失败,并把错误返回给应用进程。
-
1:不管需要多少内存,都允许申请。
-
2: 只允许分配物理内存和交换内存的大小(交换内存一般是物理内存的一半)
关闭Transparent Huge Pages(THP)
THP会造成内存锁影响redis性能,建议关闭
Transparent HugePages :用来提高内存管理的性能
Transparent Huge Pages在32位的RHEL 6中是不支持的
执行命令 echo never > /sys/kernel/mm/transparent_hugepage/enabled
把这条命令添加到这个文件中/etc/rc.local
Jedis客户端优化
- 当想要一次添加多条数据时可以使用管道,比如jedis.pipelined()
- 设置testOnBorrow=false,testOnBorrow是指在每次Jedis在跟Redis服务器发起请求之前, 先发一个test命令去检查Redis是否准备就绪,主要来应对网络和服务器不稳定性的,生产环境下高并发的情况下可以关闭,避免不必要的请求。
- 避免长耗时的查询命令。
比如不要使用keys *,原因在于keys命令会以阻塞的方式执行的,而且keys是以遍历的方式实现的,复杂度是 O(n),Redis库中的key越多,查找实现代价越大,产生的阻塞时间越长;
也尽量不要用smembers ,避免一次查询所有的成员,应该通过scan 命令进行分批的,游标式的增量遍历;