centos 7 redis geo
上周二凌晨三点,生产环境报警,说用户定位服务延迟飙到了2秒。我盯着屏幕,冷汗直接下来了。这可不是闹着玩的,对于做本地生活服务的公司来说,慢一秒,用户流失率就能涨好几个点。排查了一圈,发现是 Redis 的 Geo 功能在高并发下出现了内存碎片化,导致查询变慢。这事儿让我意识到,别光看文档说 Redis 支持 Geo,真到了 CentOS 7 这种老系统上跑生产,坑多得能让你怀疑人生。
很多人觉得装个 Redis 很简单,yum install redis 搞定。但在 CentOS 7 上,如果你直接这么干,大概率会踩雷。现在的 CentOS 7 官方源里,Redis 版本可能还停留在 3.x 或 4.x,而 Geo 功能虽然从 3.2 开始支持,但很多新特性比如 GEORADIUSBYMEMBER 的优化,在旧版本里性能并不理想。我当时就是偷懒用了默认源,结果上线后内存占用直线上升,最后不得不手动编译安装 6.2 版本的 Redis,才稳住局面。
下面这几步,是我用真金白银和加班换来的经验,希望能帮你省点头发。
第一步,别用 yum 装生产环境。去官网下载源码,解压后执行 make。这里有个坑,CentOS 7 默认的 GCC 版本可能偏低,编译时容易报错。我当时的报错信息记不清了,大概是说某种原子操作不支持。解决办法是升级 GCC,或者在编译参数里加上 -march=x86-64。这一步很关键,不然你装出来的 Redis 根本跑不动复杂的 Geo 计算。
第二步,配置文件调优。默认的 redis.conf 简直是灾难。你需要修改 maxmemory-policy 为 allkeys-lfu,因为 Geo 数据通常是最近使用的最频繁。还有,hz 参数默认是 10,建议改成 100,这样后台清理和过期检查更及时。我见过有人为了省资源把 hz 降到 1,结果 Redis 卡得像蜗牛,查询一个附近的餐厅要半天,用户直接骂娘。
第三步,数据结构设计。Geo 底层用的是 ZSet,每个成员是一个经纬度。别存全量历史轨迹,只存最近的位置。我当时犯蠢,把用户过去一年的位置都存进去了,结果一个用户占了几 MB 内存,几百个用户就把内存撑爆了。正确的做法是,每天凌晨清理一次旧数据,只保留最近 7 天的活跃位置。
第四步,查询优化。用 GEORADIUS 而不是 GEORADIUSBYMEMBER 做批量查询,虽然语义不同,但在某些场景下性能更好。另外,记得加 COUNT 参数限制返回数量,不要一次性拉取所有结果。我有一次没加 COUNT,结果返回了几千个点,网络带宽直接被打满,服务器 CPU 瞬间 100%。
最后,监控不能少。用 Prometheus 监控 Redis 的 used_memory 和 instantaneous_ops_per_sec。当内存使用率超过 80% 时,必须告警。我现在的系统里,只要内存一涨,钉钉就会响,比半夜被电话叫醒强多了。
说实话,技术这东西,文档写得再漂亮,也不如自己踩几个坑来得深刻。CentOS 7 虽然老了,但依然在很多传统企业里服役,把它用好,比盲目追新更有价值。希望这篇 centos 7 redis geo 的实战经验,能帮你避开那些隐蔽的陷阱。别信什么“一键部署”,那都是骗小白的。老老实实看日志,调参数,才是正道。
配图说明:一张 Redis 内存监控截图,显示内存使用率曲线,ALT 文字为 Redis 内存监控截图
再补充一点,测试环境一定要和生产环境配置一致。我见过太多人,开发环境好好的,一上线就崩。因为生产环境的内核参数、文件系统类型都不一样。特别是 CentOS 7 的 ext4 文件系统,对大文件写入的支持不如 xfs,如果你的 Geo 数据量特别大,建议格式化磁盘时用 xfs,能提升不少 I/O 性能。这点细节,很多人会忽略,但关键时刻能救命。