当前位置:首页 > 问答 > 正文

红色十字里用Redis搞性能统计,聊聊那些实操中最管用的技巧和经验

根据多位一线开发者在技术社区如掘金、知乎、Stack Overflow 上的经验分享,以及《Redis实战》等书籍中的相关章节,结合常见业务场景整理而成。)

说到用Redis做性能统计,尤其是在红色十字这类用户量和请求量都很大的场景里,可不能只是简单地把数据存进去就完事了,这里面有很多细节,处理不好,Redis非但帮不上忙,还可能成为瓶颈,下面就直接聊聊我们踩过坑后觉得最管用的那些技巧和经验。

第一,选对数据结构是成功的八成。 很多人一上来就用String类型存一切,这是最要命的,你要统计每天的用户活跃数,如果用String,每个用户活跃一次你就得GET一下当前的计数,再SET回去,且不说网络开销,万一同时有大量用户活跃,这个计数很可能就不准了,这时候,Redis的INCR命令就派上用场了,你只需要一个键,active_users:20231027,每次用户活跃就执行一次 INCR active_users:20231027,这个操作是原子性的,绝对保证计数准确,而且速度极快,这比用String类型自己处理加减要可靠和高效得多。

再比如,你要统计用户在一段时间内的行为,比如某个按钮的点击次数,而且可能还要按小时、按天聚合,这时候Hash结构就非常合适,你可以用一个Hash来存一天内每小时的点击量,键可以设计成 user_click:user_id:20231027,字段就是小时(如 h10 代表10点),值就是点击次数,每次点击就用 HINCRBY 命令对相应的小时字段加1,这样,你取某个用户一天24小时的点击数据,只需要一个 HGETALL 命令,非常高效,避免了为每个小时都维护一个单独的键。

第二,对付海量统计,用HyperLogLog省下大笔内存。 红色十字这种场景,经常需要统计独立用户数(UV),比如一天内有多少不同的用户访问了某个页面,如果你把每个访问的用户ID都存到一个Set里,用户量上亿的时候,这个Set会大到吓人,内存根本扛不住,Redis提供的HyperLogLog数据结构就是专门为解决这个问题而生的,它用来估算基数(不重复的元素个数),有轻微的误差率(通常小于1%),但占用的内存小得惊人,只需要12KB左右,就能统计接近2^64个不重复的元素,操作起来也简单,用 PFADD 添加元素,PFCOUNT 获取估算值,比如统计页面UV:PFADD page_uv:20231027 user_id_123,内存节省了百分之九十九点九,虽然结果是近似值,但在大多数业务场景下完全够用了。

第三,设置过期时间,别让数据“长生不老”。 统计数据的价值通常是有时效性的,你可能只需要保留最近7天或30天的统计数据,如果不给Redis的键设置过期时间(TTL),这些数据会一直占着内存,最终把Redis撑爆,在写入统计键的时候,一定要顺手加上过期时间,用 SETEX 命令在设置键的同时设置过期秒数,或者用 EXPIRE 命令单独设置,你的日活统计键 active_users:20231027,在写入时就应该设置7天后过期:EXPIRE active_users:20231027 604800,养成这个习惯,能避免很多内存泄漏的悲剧。

第四, Pipeline和批量操作,把速度提上来。 当需要一次性记录多条统计信息,或者需要查询多个统计键时,如果一个个命令发过去,网络往返时间(RTT)会成为性能杀手,Redis的Pipeline功能可以让你把多个命令打包,一次发送给Redis服务器,服务器处理完后再一次性返回所有结果,这能极大地减少网络延迟的影响,在记录一个用户登录后的一系列行为事件时,可以把多个INCRHINCRBY命令放在一个Pipeline里执行,速度会提升非常明显,但要注意,Pipeline里的命令数量也不是越多越好,一般建议每批100-1000个命令,需要根据实际情况测试调整。

第五,持久化策略要心中有数,别丢了关键数据。 Redis的数据默认存在内存里,如果服务器重启或宕机,数据就没了,对于性能统计这种可以容忍少量丢失(比如丢失几秒钟的数据)的业务,通常使用RDB持久化就够了,RDB定时做内存快照,性能开销小,但如果你的统计非常关键,一点都不能丢,那就要考虑AOF持久化,它会记录每一条写命令,数据安全性高,但会对性能有一定影响,很多时候,我们会采用混合模式,你需要根据业务对数据丢失的容忍度,在配置文件中调整save参数(控制RDB快照频率)或appendfsync参数(控制AOF刷盘策略),别等到出了故障才发现统计数据全没了。

键名设计要规范清晰。 乱七八糟的键名是维护的噩梦,一个好的键名应该能清晰地表达出它的用途、统计维度和时间范围,建议采用统一的命名规范,比如用冒号分隔的层级结构:业务:统计对象:维度:时间stats:user:login:daily:20231027,这样不仅自己看着明白,当你想用KEYSSCAN命令按模式查找或清理某一类键时,也会非常方便。

在红色十字这样的高并发环境下用Redis做性能统计,核心思路就是:用最合适的数据结构减少内存和CPU开销,用Pipeline减少网络开销,用TTL做好数据生命周期管理,并根据业务需求配置好持久化,把这些基础打牢,Redis就能成为一个极其强大且可靠的统计工具。

红色十字里用Redis搞性能统计,聊聊那些实操中最管用的技巧和经验