昨晚凌晨两点,客户群里炸锅了。
说他们的附近的人功能全乱了。
刚才还在隔壁小区,一刷新跑到隔壁市了。
这要是换做刚入行那会儿,我估计得急得跳脚。
毕竟干了15年geo这行,什么妖魔鬼怪没见过。
但这次,我点了一根烟,慢慢看了下日志。
问题出在精度和缓存策略的冲突上。
很多人一上来就搞redis的geo,觉得简单粗暴。
存个经纬度,加个半径,完事。
太天真了。
我见过太多项目,上线第一天风风光光。
第二个月,服务器崩了,数据也歪了。
为啥?因为你们没搞懂底层逻辑。
先说个最扎心的数据。
我用过三种方案对比。
纯MySQL空间索引,查询一次平均耗时45ms。
MongoDB的2dsphere,差不多30ms。
而redis的geo,只要5ms以内。
这速度,确实香。
但香归香,坑也多。
第一个坑,坐标精度。
redis的geo底层用的是geohash。
它把经纬度压缩成一个字符串。
这个字符串的长度,决定了精度。
默认是12位,大概误差在几米。
但如果你为了省内存,把精度调低。
比如只保留8位。
那误差直接飙升到几公里。
我有个客户,为了省那点Redis内存。
把精度砍了一半。
结果用户投诉,说定位不准,打车都打不到门口。
这就是典型的因小失大。
第二个坑,过期策略。
很多人喜欢给geo数据设过期时间。
比如用户在线状态,半小时过期。
这没问题。
但如果你是用redis的geo做附近的人。
并且依赖这个过期时间做业务逻辑。
那就麻烦了。
因为geohash编码和解码是有损耗的。
特别是当用户处于两个网格边界时。
稍微有点抖动,编码就变了。
这一变,你就查不到这个人了。
哪怕他就在你旁边1米。
这就是所谓的“边界效应”。
怎么解?
别只存一个坐标。
存两个,或者存一个区域ID。
或者,在应用层做去重和模糊匹配。
别全指望Redis。
第三个坑,并发写入。
高并发下,redis的geo命令是单线程的。
虽然快,但如果你每秒写入几万条。
CPU还是会飙升。
我见过一个项目,搞活动。
每秒十万QPS。
Redis直接卡死。
最后不得不加中间层,做削峰填谷。
所以,别盲目迷信redis的geo。
它适合读多写少,或者实时性要求极高的场景。
比如打车软件,找附近的司机。
比如外卖平台,找附近的骑手。
这些场景,延迟敏感,数据量相对可控。
但如果是社交软件,全量用户定位。
那还是老老实实用MySQL或者ES吧。
别为了追求那点性能,搞出一堆Bug。
最后说句掏心窝子的话。
技术选型没有最好,只有最合适。
别听大厂吹牛,说他们怎么怎么用。
你要看你的业务场景。
如果你的用户量不大,对实时性要求没那么变态。
别折腾redis的geo了。
折腾到最后,头发掉了,钱花了,问题没解决。
这才是最亏的。
记住,代码是写给人看的,顺便给机器运行。
别为了炫技,把简单的事情搞复杂。
接地气点,解决问题才是王道。
今晚回去,记得检查下你们的精度设置。
还有,别信什么“万能方案”。
每个方案都有代价。
你付得起这个代价吗?
想清楚再动手。
不然,半夜被叫醒改Bug,滋味不好受。