问题描述
在使用Azure Redis的过程中发现读写比较慢,非常卡,执行扩容6-->13GB后,过一段时间也满了。在通过门户Console连接到Reids,通过info Memory名称查看到User_memory_peak_perc指标达到99%以上,怀疑是不是该值的使用导致了Redis读写慢的问题呢?
问题根源
used_memory_peak_perc: 该值表示的是使用内存达到峰值内存的百分比。它的计算方式为:(used_memory/ used_memory_peak) * 100%,即当前redis使用内存/历史使用记录中redis使用内存峰值*100%。而used_memory_peak,表示的是redis的内存消耗峰值(以字节为单位),即历史使用记录中redis使用内存最高峰值。
所以used_memory_peak_perc指数高并不能判断当前Redis的内容使用量。而如果需要判断内存是否使用完,还是需要使用最基本的规则:MaxMemory 与 Used_Memory进行大小比较
在Redis的使用中,另一个导致慢的关键点是执行一些时间复杂度为O(N)的指令,如KEYS, HGETALL等,可以执行slowlog来查看Redis执行的慢查询日志。
- KEYS:Returns all keys matching
pattern
. While the time complexity for this operation is O(N), the constant times are fairly low. - HGETALL命令,而该命令的时间复杂度是O(N) , 这意味着Hash的field越多,当使用HgetAll获取全量数据时,性能越差,该命令的性能与field字段的数量成正比。如果频繁使用,是非常耗时的。
解决办法
升级Redis的内存空间,及设置合理的maxmemory-policy(逐出机制)。当redis内存数据达到maxmemory时,会根据maxmemory-policy配置来淘汰内存数据,以避免内存溢出(OOM: Out of Memory)。redis提供了以下8种淘汰策略:
- volatile-lru :通过尝试先删除最近不使用的(LRU)密钥来移出密钥,但只有在已设置过期的密钥中才能移出这些密钥,以便为添加的新数据腾出空间。如果查找不到数据,则回退到noeviction。
- allkeys-lru:通过尝试先删除最近不使用的(LRU)键来移出键(所有数据范围),以便为添加的新数据腾出空间。
- volatile-random:为添加新的键腾出空间,随机逐出其他键,但是仅逐出设置了过期时间的键。
- allkeys-random:随机逐出其他键,以便为添加新的键腾出空间(所有数据范围)。
- volatile-ttl:逐出设置过期的密钥,并尝试首先逐出具有较短生存时间(TTL)的密钥,以便为添加新的键腾出空间。
- noeviction:执行任何淘汰策略。当达到内存限制并且客户端尝试执行可能导致使用更多内存的命令时,将返回错误(大多数写入命令,但DEL和一些其他例外)。
- volatile-lfu:使用设置过期并且使用频率最少的键(LFU)中进行驱逐。
- allkeys-lfu:使用频率最少的键(LFU)逐出任何密钥。
参考资料
Redis Commands reference: https://redis.io/commands/