redis server went away 查看系统日志文件时发现每天定时有该错误抛出: php fatal error: uncaught exception 'redisexception' with message 'redis server went away' 抛出该问题的脚本为统计脚本,需要读取前一天数据并入库,最初以为是redis读取太频繁
redis server went away
查看系统日志文件时发现每天定时有该错误抛出:
php fatal error: uncaught exception 'redisexception' with message 'redis server went away'
抛出该问题的脚本为统计脚本,需要读取前一天数据并入库,最初以为是redis读取太频繁造成的,但将数据导到测试机后执行脚本发现不会出现该情况,仔细调试发现手动执行时有一行代码没有执行,若执行该行则十分缓慢。该行代码为:
$redis->delete($redis->keys($pre_key_del.'*'));
查看手册有相应提示:
keys 的速度非常快,但在一个大的数据库中使用它仍然可能造成性能问题,如果你需要从一个数据集 中查找特定的 key ,你最好还是用 redis 的集合结构(set)来代替。
登录redis通过info查看,内存使用25g多,而key也有1.44亿了。。。reids中有大量无用而又未设置过期时间的key存在。设置个过期时间,举手之劳的事,还是有必要的。
used_memory_human:24.72g db0:keys=144856453,expires=25357
通过测试机执行 keys prefix* 导致redis卡死,其他连接也连不上。所以定位到问题出现在keys命令上,也正如手册上说的造成性能问题。
如何删除未用到的key?
大部分key是有规律的,有特定前缀,需要拿到特定前缀的key然后删除,网上有这样的命令:
redis-cli -a redis-pwd -n 0 keys "preffix*" | xargs redis-cli -p 6379 -a redis-pwd -n 0 del
测试机执行keys "preffix-1*"时间大概40多s,这意味着redis要停40s+,而前缀是按天设置的,这样子需要操作多次,因为业务的原因,不允许这么操作,分分钟都是钱~
最后想到的办法是先从测试机上把满足条件的key导到文本,前面的语句通过cat文本去拿。如:
redis-cli -p 6380 -a redis-pwd keys "preffix-1*" > /home/keys_redis/preffix-1
然后通过这些数据删掉生产环境上的key。
cat /home/keys_redis/preffix-1 | xargs redis-cli -a redis-pwd -n 0 del
删除的速度非常快,内存耗的也挺快,感觉像是有多少耗多少的。执行之后key的数量减少了95%+,内存也从25g降到了2g。不过有一个指数升高了 ———— mem_fragmentation_ratio,前后的memory对比:
# memory 处理前 used_memory:26839186032 used_memory_human:25.00g used_memory_rss:23518339072 used_memory_peak:26963439000 used_memory_peak_human:25.11g used_memory_lua:31744 mem_fragmentation_ratio:0.88 mem_allocator:jemalloc-3.2.0 # memory 处理后 used_memory:2399386704 used_memory_human:2.23g used_memory_rss:4621533184 used_memory_peak:26963439000 used_memory_peak_human:25.11g used_memory_lua:31744 mem_fragmentation_ratio:1.93 mem_allocator:jemalloc-3.2.0
mem_fragmentation_ratio的问题可能还需要优化下,从redis这个问题可以看到,设置cache的时候我们也需要考虑到cache的维护问题,是否该设置cache的过期时间,key的命名方式如何管理,不能只想着把数据塞进去就万事大吉了。
相关网站:
redis
redis 命令参考
【说明】:本文章由站长整理发布,文章内容不代表本站观点,如文中有侵权行为,请与本站客服联系(QQ:)!