Redis在概念上与我使用的传统SQL数据库不同,我正在试图弄清楚它是否适合我的项目...我一直在环顾四周但似乎找不到我的答案问题
我有一组我需要存储的用户,每个用户都有一个唯一的ID和几个与之关联的值(例如他们的名字)。看起来我可以简单地将它们存储为哈希:
user:fef982dcfe1a7bcba4849b4c281bba95
"username" "andrewm" "name" "Andrew"
我还有一堆我要存储的邮件,每条邮件都有一些属性,例如发件人和收件人:
message:1a7bcba4849b4c281bfef98a952dcfeb
"sender" "fef982dcfe1a7bcba4849b4c281bba95" "recipient" "82dcfe1a7bcba4849b4c281bba95fef9" "message" "Hi!"
我的问题是,如何检索特定用户发送的所有邮件(由其哈希指定)。我应该使用传统的关系数据库,还是像MongoDB这样的NoSQL数据库(我之前使用过)?如果是这样,有没有人对高性能商店有任何建议?我不会做任何真正的搜索(即MySQL LIKE
查询) - 只是键值查找,真的。
答案 0 :(得分:9)
使用Redis建模这些数据当然是可能的,但您需要考虑数据结构和访问路径。使用Redis时,不会隐式管理访问路径(与RDBMS / MongoDB中的索引一样)。
对于提供的示例,您可以:
user:<user hash> -> hash of user properties
user:<user hash:sent -> set of <msg hash>
user:<user hash>:received -> set of <msg hash>
message:<msg hash> -> hash of message properties
添加/删除邮件意味着在添加/删除邮件对象本身的基础上维护与发件人和收件人相对应的*:sent和*:收到的设置。
检索给定用户的已发送或已接收消息只是一个SMEMBERS命令,如果您想要同时检索消息的属性,则为SORT:
# Get a list of message hash codes only in one roundtrip
smembers user:<user hash>:received
# Get a list of message contents in one roundtrip
sort user:<user hash>:received by nosort get message:*->sender get message:*->message
有关使用排序的基本原理,请参阅:
注1:使用Redis最好使用整数作为键而不是UUID或哈希码(特别是在集合中),因为它们以更有效的方式存储。
注2:如果您需要订购消息,则必须使用列表而不是集合。结果是只能删除最旧的消息,并且只能以有效的方式添加新设置的消息。您可能还要为所有消息添加全局列表。
答案 1 :(得分:1)
Redis的基本数据类型不支持多条件查询,全文搜索等。因此,我们修改了Redis源代码,并将Redis转换为可通过辅助索引像SQL数据一样使用的数据库。
该项目的主页为https://oncedb.com
OnceDB不会更改Redis的数据存储结构。 Redis数据库文件可以直接在OneDB中操作,然后返回给Redis使用。
全文搜索的性能很差。您可以通过创建索引来提高性能。该方法是为索引字段创建有序列表,然后在执行条件查询时对这些有序列表执行交集查询操作。
# Create hash data
hmset article:001 poster dota visit 21 key js
hmset article:002 poster dota visit 11 key c
hmset article:003 poster like visit 34 key js
hmset article:004 poster like visit 44 key c
然后我们为以上字段创建索引,权重得分设置为:202000201,一个关于时间的整数,该值是商品的ID值
# Create indexed
zadd *article.poster:dota 20200201 001 20200201 002
zadd *article.poster:like 20200201 003 20200201 004
zadd *article.key:js 20200201 001 20200201 003
zadd *article.key:c 20200201 002 20200201 004
# "visit" using its value as the weight score
zadd *article.visit 21 001 11 002 34 003 44 004
找到两个索引* article.key:js和* article.poster:dota的交集并将它们存储在* tmp1有序列表中:
zinterstore *tmp1 2 *article.key:js *article.poster:dota
> 1
然后* tmp1存储满足key = js和poster = dota条件的ID集:
zrange *tmp1 0 -1
> 001
您可以使用zrangehmget命令来打印相应的HASH值:
zrangehmget *tmp1 0 -1 article: key poster
1) 001
2) 40400402
3) js
4) dota
5)
6)
结果与直接全文搜索键= js和发帖人= dota相同
hsearch article:* key = js poster = dota
1) article:001
2) js
3) dota
例如,要搜索访问次数在20到30之间且key = js的数据,可以通过控制权重来实现
创建一个临时索引,仅占用* article.visit的权重和key = js的数据
zinterstore *tmp2 2 *article.key:js *article.visit weights 0 1
> 2
获取20到30之间的数据
zrangebyscore *tmp2 20 30
> 001
您可以使用zrangehmgetbyscore打印相应的哈希数据:
zrangehmgetbyscore *tmp2 20 30 article: key visit
1) 001
2) 21
3) js
4) 21
5)
6)
结果与使用全文搜索的结果一致:
hsearch article:* visit >= 20 visit <= 30 key = js
1) article:001
2) 21
3)
4) js
因为有两个相同的字段,visit> = 20 visit <= 30,所以搜索结果将只输出一个,而第三行中重复的字段将输出为空。
更多的OnceDB扩展说明可以查看:Search, query, calculate, and sum instructions in OnceDB
创建和维护Redis索引不是很方便。修改数据后,OneDB可以选择自动创建辅助索引。
使用upsert / insert / update指令和特殊运算符自动创建索引:
上面的示例可以写为:
upsert article id @ 001 poster ? dota visit / 21 key ? js
upsert article id @ 002 poster ? dota visit / 11 key ? c
upsert article id @ 003 poster ? like visit / 34 key ? js
upsert article id @ 004 poster ? like visit / 44 key ? c
操作员:
@:主键 ?:组索引 /:排序索引
操作后将自动创建索引:* article * article.poster:dota * article.poster:like * article.visit * article.key:js * article.key:c
对于具有索引的字段,可以使用find命令在索引字段中进行查询。例如,查询:key = js和poster = dota的数据。您可以使用 ”?”指示这两个字段是分组索引:
find article 0 -1 key ? js poster ? dota
1) 1
2) article:001
3) js
4) dota
1代表数据总量。如果为-1,则表示使用全文本搜索,性能较差。
您可以添加@以指定索引范围,并使用+指定用于分数权重范围的索引字段。
find article 0@20 -1@30 key ? js visit /+ *
1) 1
2) article:001
3) js
4) 21
OnceDB不存储索引定义。删除时,您需要手动指示哪些字段包含索引。您需要指定字段名称和索引运算符。
remove article @ 001 key ? poster ? visit /
您还可以自定义索引名称和体重得分。有关更多说明,请参见:OnceDB data modification and query help documentation