2012服务器如何做网站,怎么做淘宝企业网站,个人主页源码下载,asp.net 网站 代理一、Redis 内存回收 Redis 之所以性能强#xff0c;最主要的原因就是基于内存存储。然而单节点的 Redis 其内存大小不宜过大#xff0c;会影响持久化或主从同步性能。 我们可以通过修改配置文件来设置 Redis 的最大内存#xff1a;
# 格式#xff1a;
# maxmemory byt…一、Redis 内存回收 Redis 之所以性能强最主要的原因就是基于内存存储。然而单节点的 Redis 其内存大小不宜过大会影响持久化或主从同步性能。 我们可以通过修改配置文件来设置 Redis 的最大内存
# 格式
# maxmemory bytes# 例如
maxmemory 1gb当内存使用达到上限时就无法存储更多数据了。为了解决这个问题Redis 提供了一些策略实现内存回收内存过期策略和内存淘汰策略。
二、过期策略 在学习 Redis 缓存的时候我们说过可以通过 expire 命令给 Redis 的 key 设置 TTL存活时间 可以发现当 key 的 TTL 到期以后再次访问 name 返回的是 nil说明这个 key 已经不存在了对应的内存也得到释放。从而起到内存回收的目的。 这里有两个问题需要我们思考Redis 是如何知道一个 key 是否过期呢是不是 TTL 到期就立即删除了呢
2.1 DB 结构 Redis 本身是一个典型的 key-value 内存存储数据库因此所有的 key、value 都保存在之前学习过的 Dict 结构中。不过在其 database 结构体中有两个 Dict一个用来记录 key-value另一个用来记录 key-TTL。其结构体如下图所示 所以 Redis 是利用两个 Dict 分别记录 key-value 对及 key-ttl 对来知道 key 是否过期了。 是不是 TTL 到期就立即删除了呢当然不是还要经历惰性删除和周期删除两个阶段。
2.2 惰性删除 惰性删除顾明思议并不是在 TTL 到期后就立刻删除而是在访问一个 key 的时候检查该 key 的存活时间如果已经过期才执行删除。
2.3 周期删除 周期删除顾明思议是通过一个定时任务周期性的抽样部分过期的 key然后执行删除。执行周期有两种模式分别为 SLOW 模式和 FAST 模式。 SLOW 模式Redis 服务初始化函数 initServer() 中设置定时任务按照 server.hz 的频率来执行过期 key 清理模式为 SLOW。 FAST 模式Redis 的每个事件循环前会调用 beforeSleep() 函数执行过期 key 清理模式为 FAST。
2.3.1 SLOW 模式规则 1、执行频率受 server.hz 影响默认为 10即每秒执行 10 次每个执行周期 100ms。 2、执行清理耗时不超过一次执行周期的 25%.默认 slow 模式耗时不超过 25ms 3、逐个遍历 db逐个遍历 db 中的 bucket抽取 20 个 key 判断是否过期 4、如果没达到时间上限25ms并且过期 key 比例大于 10%再进行一次抽样否则结束
2.3.2 FAST 模式规则
过期 key 比例小于 10% 不执行 1、执行频率受 beforeSleep() 调用频率影响但两次 FAST 模式间隔不低于 2ms 2、执行清理耗时不超过 1ms 3、逐个遍历 db逐个遍历 db 中的 bucket抽取 20 个 key 判断是否过期 4、如果没达到时间上限1ms并且过期 key 比例大于 10%再进行一次抽样否则结束。
2.4 小结
RedisKey 的 TTL 记录方式 1、在 RedisDB 中通过一个 Dict 记录每个 Key 的 TTL 时间
过期 key 的删除策略 1、惰性清理每次查找 key 时判断是否过期如果过期则删除 2、定期清理定期抽样部分 key判断是否过期如果过期则删除。
定期清理的两种模式 1、SLOW 模式执行频率默认为 10每次不超过 25ms 2、FAST 模式执行频率不固定但两次间隔不低于 2ms每次耗时不超过 1ms
三、淘汰策略 我们上一小节学习了 redis 的过期策略但是这种方式只能将过期的 key 给它移除。但是在一些庞大的项目上数据量非常的多。很有可能仅仅淘汰过期的 key也难以满足内存的使用。内存也有可能达到上限。此时就需要内存淘汰策略了。
3.1 内存淘汰 就是当 Redis 内存使用达到设置的上限时主动挑选部分 key 删除以释放更多内存的流程。 只要有任何的命令写入redis 都会检查内存是否够用只要不够都会去清理内存如下代码Redis 会在处理客户端命令的方法 processCommand() 中尝试做内存淘汰
int processCommand(client *c) {// 如果服务器设置了server.maxmemory属性并且没有执行lua脚本if (server.maxmemory !server.lua_timedout) {// 尝试进行内存淘汰performEvictionsint out_of_memory (performEvictions() EVICT_FAIL);// ...if (out_of_memory reject_cmd_on_oom) {rejectCommand(c, shared.oomerr);return C_OK;}// ....}
}3.2 淘汰策略 Redis 支持 8 种不同策略来选择要删除的 key我们也可以修改配置文件来设置不同的策略设置的位置如下图所示 1、noeviction 不淘汰任何 key但是内存满时不允许写入新数据会报错默认就是这种策略。 2、volatile-ttl 对设置了 TTL 的 key比较 key 的剩余 TTL 值TTL 越小越先被淘汰。 3、allkeys-random对全体 key 随机进行淘汰。也就是直接从 db-dict 中随机挑选。 4、volatile-random对设置了 TTL 的 key 随机进行淘汰。也就是从 db-expires 中随机挑选。 5、allkeys-lru 对全体 key基于 LRU 算法进行淘汰。 6、volatile-lru 对设置了 TTL 的 key基于 LRU 算法进行淘汰。 7、allkeys-lfu 对全体 key基于 LFU 算法进行淘汰。 8、volatile-lfu 对设置了 TTL 的 key基于 LFU 算法进行淘汰。
比较容易混淆的有两个 LRULeast Recently Used最少最近使用。用当前时间减去最后一次访问时间这个值越大则淘汰优先级越高。 LFULeast Frequently Used最少频率使用。会统计每个 key 的访问频率值越小淘汰优先级越高。
3.3 整体流程图