Redis里存对象那些事儿,简单聊聊怎么用Redis当对象仓库
- 问答
- 2025-12-23 08:00:38
- 3
(Redis实战笔记)里提到过,Redis本身是一个键值数据库,它最直接能存的就是字符串,但咱们日常开发中,处理的基本都是对象,比如用户信息、商品详情、订单数据等等,这些对象通常包含多个字段,那怎么把这些结构复杂的对象塞进Redis这个简单的键值世界里呢?这事儿有几个常见的路子,各有各的打算。
最直接的办法,就是把对象序列化。(比如用Java的话,可能用JDK自带的序列化,或者更高效的JSON、Protobuf等)变成一个字符串,然后直接用这个对象的ID作为键,把序列化后的字符串存进去,一个用户对象,ID是123,序列化成JSON字符串后,SET user:123 '{"name": "张三", "age": 30, "city": "北京"}',取的时候,根据键user:123拿到字符串,再反序列化回对象就行了,这个方法的好处是简单粗暴,一次读写整个对象,对于总是需要操作对象全部字段的场景挺方便,但缺点也同样明显,如果想只修改对象的某一个字段(比如只把年龄从30改成31),也得把整个字符串取出来,反序列化,修改字段,再序列化,最后写回去,这中间涉及网络传输和CPU计算,如果对象很大或并发很高,开销不小,没法直接用Redis的命令对对象内部的字段进行单独操作。
(Redis实战笔记)里还介绍了另一种思路:用哈希(Hash)来存,Redis的Hash结构非常适合用来表示对象,它本身就是一个字段和值的映射表,这正好对应对象的属性和属性值,还拿那个用户对象举例,我们可以这样存:HSET user:123 name "张三" age 30 city "北京",这里,键依然是user:123,但它对应的值不是一个字符串,而是一个Hash结构,里面包含了name、age、city三个字段,这种方式的好处就大多了,可以非常精细地操作对象,想改年龄?直接HINCRBY user:123 age 1就行了,原子操作,不用动其他字段,想获取用户名和城市?可以用HMGET user:123 name city,只返回指定的字段,节省网络流量,这对于对象字段很多但每次只关心其中几个的场景非常高效,它也有不太方便的地方,如果想一次性获取整个对象的所有字段,虽然可以用HGETALL命令,但如果字段非常多,这个命令可能会比较慢(被称为“慢查询”的潜在风险之一),哈希结构不支持直接嵌套复杂的数据类型,如果对象内部还有复杂的子对象,处理起来会麻烦一些。
除了这两种主流方法,有时候也会根据特殊需求用到其他结构。(如果对象的某个字段是一个列表,比如用户的收货地址列表,可能会选择用一个新的键,比如user:123:addresses,用一个Redis的列表(List)或集合(Set)来存储,而不是强行塞进Hash的一个字段里,这其实就是一种数据拆分的策略。
到底该选哪种方式呢?(这得看具体情况)没有绝对的好坏,得看你的业务场景,如果你的对象几乎总是被整体访问和修改,字段不多,或者修改不频繁,那么序列化成字符串存起来,省心又省力,如果你的对象很大,而且经常只需要读写或更新其中一小部分字段,那么用Hash结构会带来显著的性能优势,还有一种情况是,如果你的应用需要用到Redis的过期时间(TTL)功能来让数据自动失效,要注意的是,过期时间只能设置在顶层的键上,对于序列化字符串的方式,直接对user:123设过期时间就行,对于Hash方式,也是对整个user:123这个键设过期时间,它内部的所有字段会一起过期。
把Redis当对象仓库,关键是想清楚你打算怎么“用”这个对象,是把它当作一个黑盒整体搬来搬去,还是经常要打开盒子只取几样东西或者只换一个零件,想明白了这个,选择哪种存储方式也就清晰了,在实际项目中,这两种方式常常是共存的,针对不同类型的数据采用最合适的策略,这样才能真正发挥Redis的性能优势。
本文由芮以莲于2025-12-23发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:http://waw.haoid.cn/wenda/66791.html
