我一直在遇到一些情况,我存储的信息要比Redis的任何简单数据结构都要复杂。我仍然想使用Redis,但我想知道在理想情况下他们是否想使用嵌套结构时是否有任何标准替代品?
答案 0 :(得分:8)
您基本上有两种策略:
您可以序列化复杂对象并将其存储为字符串。我们建议使用json或msgpack作为序列化格式。这很容易从大多数客户端语言进行操作。如果需要服务器端访问,则服务器端Lua脚本可以轻松编码/解码此类对象,因为Redis是使用msgpack和json支持Lua编译的。
您可以将对象拆分为不同的键。您可以存储多个键,例如user:id,user:id:address_list,user:id:document_lists等,而不是将user:id和复杂数据结构存储到此ID中。如果需要原子性,请使用流水线MULTI / EXEC块可用于保证数据的一致性,并汇总往返。
请参阅此答案中的一个简单示例:
Will the LPUSH command work on a record that was initialized from JSON?
最后,Redis不是面向文档的数据库。如果你真的有很多复杂的文档,也许你可以通过MongoDB,ArangoDB,CouchDB,Couchbase等解决方案更好地服务......
答案 1 :(得分:1)
当您需要修改对象时,将复杂对象序列化为字符串并将字符串保存到Redis效率很低。由于您必须将字符串取回客户端,将其反序列化为对象,对其进行修改,再次将其序列化为字符串,然后将其保存回Redis。太多的工作...
现在是2019年,并且有一些新的Redis模块可以使Redis支持嵌套数据结构,例如RedisJSON,redis-protobuf。
Desclaimer :我是redis-protobuf的作者,因此我将在此模块上提供一些示例。同样, redis-protobuf 比 RedisJSON 更快,存储效率更高,因为它使用文本格式以外的二进制格式来序列化/反序列化数据。
首先,您需要在Protobuf format中定义嵌套的数据结构并将其保存到本地文件:
syntax = "proto3";
message SubMsg {
string s = 1;
int32 i = 2;
}
message Msg {
int32 i = 1;
SubMsg sub = 2;
repeated int32 arr = 3;
}
然后在 redis.conf 中使用以下配置加载模块:
loadmodule /path/to/libredis-protobuf.so --dir proto-directory
之后,您可以读写嵌套的数据结构:
PB.SET key Msg '{"i" : 1, "sub" : {"s" : "string", "i" : 2}, "arr" : [1, 2, 3]}'
PB.SET key Msg.i 10
PB.GET key Msg.i
PB.SET key Msg.sub.s redis-protobuf
PB.GET key Msg.sub.s
PB.SET key Msg.arr[0] 2
PB.GET key Msg.arr[0]
请检查doc以获得详细信息。如果您对redis-protobuf有任何疑问,请随时let me know。