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

Redis存储结构怎么优化才能更快更省空间,聊聊那些实用的技巧

关于Redis怎么用得更快更省地方,我结合一些实战经验和像《Redis设计与实现》这本书里的思路,还有官方文档里的一些建议,跟你聊聊几个实在的技巧。

在省空间这块,关键是想尽办法让存进去的数据“变小”,一个很直接的办法是,如果数据本身是数字,尤其是整数,尽量用整数存,不要用字符串,比如用户年龄“25”,存成字符串“25”要占更多字节,而Redis内部对整数有特殊处理,存成整数能省很多空间,这其实是Redis对象系统的一个基础设计,整数是最省的一种类型。

别小看Redis提供的几种数据结构,用对了能省一大笔,比如要存一个用户的多个字段,比如姓名、年龄、城市,很多人可能用三个独立的字符串键(user:1001:name, user:1001:age...),这会产生大量小键,额外开销很大,改用哈希(Hash)结构,用一个键(user:1001)把多个字段打包存起来,管理方便,更重要的是能显著减少内存占用,因为Redis底层对于哈希结构有两种编码方式,当字段数量不多、值不大时,会采用一种非常紧凑的存储方式(ziplist,在较新版本中已被listpack替代),比单独存字符串键省多了,这个转换的阈值可以在配置文件里调整(hash-max-ziplist-entries和hash-max-ziplist-value),根据你的数据特点调一调,效果立竿见影,类似的原则也适用于列表(List)、集合(Set)和有序集合(Zset),它们在小数据量时都有这种紧凑的存储模式。

对于有序集合,有个典型场景是排行榜,如果分数(score)是整数,可以试试用“位”来合并存储,比如把实际分数乘以10000转换成整数,和用户ID拼接成一个新分数,这样在范围查询时,利用位操作就能高效过滤,一个Zset就能搞定,避免了用多个结构。

Redis存储结构怎么优化才能更快更省空间,聊聊那些实用的技巧

再来,给数据设置合理的过期时间(TTL)不仅是好习惯,本质上也是一种空间优化,让不活跃的数据自动过期淘汰,内存利用率自然就高了,根据业务特点选择合适的淘汰策略(maxmemory-policy),volatile-lru,让Redis在内存不足时自己清理,避免撑爆。

说到更快,思路主要是减少网络往返和降低Redis自身的CPU负担,能用一条命令完成的,绝不用两条,最典型的就是管道(Pipeline),把多个命令打包一次发送,网络开销成倍下降,对于多个键的读写,如果它们能在同一个哈希标签(hashtag)下,就能用上集群模式下的管道,进一步提升效率。

Redis存储结构怎么优化才能更快更省空间,聊聊那些实用的技巧

批量操作也比单个操作强得多,比如用 MSET/MGET 一次读写多个字符串,用 HMSET/HMGET 处理哈希的多个字段,对于大量数据的插入,官方甚至建议用生成并执行Redis协议格式文件的方式,或者利用 Lua 脚本,把逻辑放到服务端执行,避免来来回回地传输数据和命令。

还有一个容易被忽略的点:避免使用会阻塞服务的命令,比如在线上环境对一个大集合执行 KEYS 命令,可能会让服务卡住一会儿,应该用 SCAN 系列命令来渐进式地遍历,虽然慢一点,但不会阻塞。

大键是性能杀手,一个哈希里存了几十万个字段,或者一个字符串值有好几MB,都会导致操作变慢,甚至引发持久化、主从复制时的问题,定期用 redis-rdb-tools 这类工具分析内存快照,找出这些“大块头”,然后想办法拆分它们,比如把一个大哈希按某种规则拆成多个小哈希。

优化Redis就是在这几个方面下功夫:让数据更小(用对结构、压缩数字、启用压缩)、让操作更“批量”(管道、批量命令、Lua脚本)、保持数据精简(设置TTL、清理大键),这些技巧都不复杂,但结合自己业务的数据特性和访问模式去灵活应用,往往能收获意想不到的效果。

备用