redis所有的数据都在内存中,而内存又是非常宝贵的资源。常用的内存优化方案有如下几部分:
1、配置优化
2、缩减键值对象
3、命令处理
4、缓存淘汰方案
一、配置优化
1、linux配置优化
内存分配
echo never > /sys/kernel/mm/transparent_hugepage/enabled
为使机器重启后THP配置依然生效,可以在/etc/rc.local 中追加 echo never>/sys/kernel/mm/transparent_hugepage/enabled
OOM(Out Of Memory)killer 机制是指 Linux 操作系统发现可用内存不足时,强制杀死一些用户进程(非内核进程),来保证系统有足够的可用内存 进行分配。 为使配置在重启 Linux 操作系统后立即生效,只需要在/etc/sysctl.conf 追加 vm.swappiness={bestvalue}即可 echo vm.swappiness={bestvalue} >> /etc/sysctl.conf
Redis 允许同时有多个客户端通过网络进行连接,可以通过配置 maxclients 来限制最大客户端连接数。对 Linux 操作系统来说,这些网络连接都是文件 句柄。假设当前 open files 是4096,那么启动 Redis 时会看到如下日志:
#You requested maxclients of 10000 requiring at least 10032 max file descriptors.
#Redis can’t set maximum open files to 10032 because of OS error: Operation not permitted.
#Current maximum open files is 4096. Maxclients has been reduced to 4064 to compensate for low ulimit. If you need higher maxclients increase ‘ulimit –n’ .
解释如下:
第一行:Redis 建议把 open files 至少设置成10032,那么这个10032是如何来的呢?因为 maxclients 默认是10000,这些是用来处理客户端连接的,除此 之外,Redis 内部会使用最多32个文件描述符,所以这里的10032=10000+32。
第二行:Redis 不能将 open files 设置成10032,因为它没有权限设置。
第三行:当前系统的 open files 是4096,所以将 maxclients 设置成4096-32=4064个,如果你想设置更高的 maxclients,请使用 ulimit-n 来设置。
从上面的三行日志分析可以看出 open files 的限制优先级比 maxclients 大。 Open files 的设置方法如下:
ulimit –Sn {max-open-files}
2、Redis配置优化
二、缩减键值对象
降低Redis内存使用最直接的方式就是缩减键(key)和值(value)的长度。
三. 命令处理
Redis基于C/S架构模式,基于Redis操作命令是解决响应延迟问题最关键的部分,因为Redis是个单线程模型,客户端过来的命令是按照顺序执行的。比较常见的 延迟是带宽,通过千兆网卡的延迟大约有200μs。倘若明显看到命令的响应时间变慢,延迟高于200μs,那可能是Redis命令队列里等待处理的命令数量比较多
要分析解决这个性能问题,需要跟踪命令处理数的数量和延迟时间。
比如可以写个脚本,定期记录total_commands_processed的值。当客户端明显发现响应时间过慢时,可以通过记录的total_commands_processed历史数据值来判 断命理处理总数是上升趋势还是下降趋势,以便排查问题 在info信息里的 total_commands_processed字段显示了Redis服务处理命令的总数
解决方案:
1.使用多参数命令:若是客户端在很短的时间内发送大量的命令过来,会发现响应时间明显变慢,这由于后面命令一直在等待队列中前面大量命令执行完毕。有 个方法可以改善延迟问题,就是通过单命令多参数的形式取代多命令单参数的形式。
举例来说 循环使用LSET命令去添加1000个元素到list结构中,是性能比较差的一种方式,更好的做法是在客户端创建一个1000元素的列表,用单个命令LPUSH或 RPUSH,通过多参数构造形式一次性把1000个元素发送的Redis服务上。下面是Redis的一些操作命令,有单个参数命令和支持多个参数的命令,通过这些命令可 尽量减少使用多命令的次数。
2.管道命令:另一个减少多命令的方法是使用管道(pipeline),把几个命令合并一起执行,从而减少因网络开销引起的延迟问题。因为10个命令单独发送到服务端 会引起10次网络延迟开销,使用管道会一次性把执行结果返回,仅需要一次网络延迟开销。Redis本身支持管道命令,大多数客户端也支持,倘若当前实例延迟 很明显,那么使用管道去降低延迟是非常有效的
四、缓存淘汰优化
redis 内存数据集大小上升到一定大小的时候,就会进行数据淘汰策略。如果不淘汰经常不用的缓存数据,那么正常的数据将不会存储到缓存当中。
我们通过配置redis.conf中的maxmemory这个值来开启内存淘汰功能。
值得注意的是,maxmemory为0的时候表示我们对Redis的内存使用没有限制
根据应用场景,选择淘汰策略
内存淘汰的过程
首先,客户端发起了需要申请更多内存的命令(如set)。
然后,Redis检查内存使用情况,如果已使用的内存大于maxmemory则开始根据用户配置的不同淘汰策略来淘汰内存(key),从而换取一定的内存。
最后,如果上面都没问题,则这个命令执行成功。
动态改配置命令
此外,redis支持动态改配置,无需重启。
config set maxmemory 100000
config set maxmemory-policy noeviction
volatile-lru
allkeys-lru
volatile-lfu
allkeys-lfu
volatile-ttl
volatile-random
allkeys-random
no-enviction
当内存达到限制的时候,不淘汰任何数据,不可写入任何数据集,所有引起申请内存的命令会报错。
算法文章:(https://blog.csdn.net/ZYZMZM_/article/details/90546812)
如何选择淘汰策略
下面看看几种策略的适用场景
另外,volatile-lru策略和volatile-random策略适合我们将一个Redis实例既应用于缓存和又应用于持久化存储的时候,然而我们也可以通过使用两个Redis实例来达 到相同的效果,值得一提的是将key设置过期时间实际上会消耗更多的内存,因此我们建议使用allkeys-lru策略从而更有效率的使用内存