搜索redis db的值 [英] Searching in values of a redis db

查看:47
本文介绍了搜索redis db的值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是使用 Redis DB 的新手.在阅读了一些文档并查看了 Internet 上的一些示例并扫描了 stackoverflow.com 后,我可以看到 Redis 非常快,扩展性很好,但这需要付出代价,我们必须考虑我们的数据将如何在设计时访问以及它们将必须经历的操作.我可以理解这一点,但对于使用普通的旧 SQL 在数据中搜索如此简单但又很慢的内容,我感到有些困惑.我可以用 KEY 命令以一种方式完成它,但它是一个 O(N) 操作而不是 O(log(N)).所以我会失去Redis的优势之一.

I am a novice in using Redis DB. After reading some of the documentation and looking into some of the examples on the Internet and also scanning stackoverflow.com, I can see that Redis is very fast, scales well but this costs the price that we have to think out how our data will be accessed at the design time and what operations they will have to undergo. This I can understand but I am a little confused about searching in the data what was so easy, however slow, with the plain old SQL. I could do it in one way with the KEY command but it is an O(N) operation and not O(log(N)). So I would lose one of the advantages of Redis.

更有经验的同事在这里怎么说?

What do more experienced colleagues say here?

让我们举一个例子用例:我们需要存储个人数据大约.100.000 人,这些数据需要按姓名、电话号码进行搜索.

Let's take an example use case: we have need to store personal data for approx. 100.000 people and those data need to be searched by name, phone nr.

为此,我将使用以下结构:

For this I would use the following structures:

1. SET for storing all persons' ids {id1, id2, ...} 
2. HASH for each person to store personal data and name it 
like map:<id> e.g. map:id1{name:<name>, phone:<number>, etc...}

解决方案 1:

1. HASH for storing all persons' ids but the key should be the phone number
2. Then with the command KEY 123* all ids could be retrieved who have a phone number 
sarting with 123. On basis of the ids also the other personal data could be retrieved.
3. So forth for each data to be searched for a separate HASH should be created.

但是这个解决方案的一个主要缺点是属性值也必须是唯一的,这样HASH中电话号码和id的分配就会是明确的.另一方面,O(N) 运行时并不理想.

But a major drawback of this solution is that the attribute values must also be unique, so that the assigment of the phone number and the ids in the HASH would be unambiguous. On the other hand, O(N) runtime is not ideal.

此外,这会占用更多的空间,并且KEY 命令会降低访问性能. (http://redis.io/commands/keys)

Moreover, this uses more space than would be necessary and the KEY command deteriorates the access performance. (http://redis.io/commands/keys)

应该如何以正确的方式完成?我也可以想象 id 会进入 ZSET,搜索所需的数据可能是分数,但这只能处理范围而不是 serache.

How should it be done in the right way? I could also imagine that ids would go in a ZSET and the data needed search could be the scores but this make only possible to work with ranges not with seraches.

也提前谢谢你,问候,塔玛斯

Thank you also in advance, regards, Tamas

答案摘要:实际上,这两个响应都说明 Redis 不是为了搜索键的值而设计的.如果此用例是必要的,则需要实施解决方法,如我的原始解决方案或以下解决方案所示.

Answer summary: Actually, both responses state that Redis was not designed to search in the values of the keys. If this use case is necessary, then either workarounds need to be implemented as shown in my original solution or in the below solution.

下面的Eli 的解决方案比我原来的方案有更好的性能,因为对键的访问可以被认为是常量,只有 id 列表需要迭代,以便访问这会给 O(const) 运行时.此数据模型还允许一个人可能与其他人拥有相同的电话号码,诸如姓名等......因此1-n 关系也是可能的(我会用旧的 ERD 术语说).

The below solution by Eli has a much better performance, than my original one because the access to the keys can be considered constant, only the list of ids needs to be iterated through, for the access this would give O(const) runtime. This data model also allows that one person might have the same phone number as someone else and so on also for names etc... so 1-n relationship is also possible (I would say with old ERD terminology).

此解决方案的缺点是,它比我的占用更多空间,并且电话号码的起始数字仅已知,无法搜索.

The drawback of this solution is, that it consumes much more space than mine and phone numbers whose starting digits are known only, could not be searched.

感谢两位的回答.

推荐答案

Redis 适用于您需要以非常高的频率访问和更新数据以及您可以从数据结构(散列、集合、列表、字符串或排序集).它用于填充非常特定的用例.如果您有一个非常灵活的搜索等通用用例,那么为此目的构建的东西(例如弹性搜索或 SOLR)会更好地为您服务.

Redis is for use cases where you need to access and update data at very high frequency and where you benefit from use of data structures (hashes, sets, lists, strings, or sorted sets). It's made to fill very specific use cases. If you have a general use case like very flexible searching, you'd be much better served by something built for this purpose like elastic search or SOLR.

也就是说,如果您必须在 Redis 中执行此操作,我会这样做(假设用户可以共享姓名和电话号码):

That said, if you must do this in Redis, here's how I'd do it (assuming users can share names and phone numbers):

name:some_name -> set([id1, id2, etc...])
name:some_other_name -> set([id3, id4, etc...])

phone:some_phone -> set([id1, id3, etc...])
phone:some_other_phone -> set([id2, id4, etc...])

id1 -> {'name' : 'bob', 'phone' : '123-456-7891', etc...}
id2 -> {'name' : 'alice', 'phone' : '987-456-7891', etc...}

在这种情况下,我们为每个姓名(以name:"为前缀)和每个电话号码(以phone:"为前缀)制作一个新密钥.每个键都指向一组 id,这些 id 包含您想要为用户提供的所有信息.例如,当您搜索手机时,您会执行以下操作:

In this case, we're making a new key for every name (prefixed with "name:") and every phone number (prefixed "phone:"). Each key points to a set of ids that have all the info you want for a user. When you search, for a phone, for example, you'll do:

HGETALL 'phone:123-456-7891'

然后遍历结果并以您选择的语言返回每个(在我们的示例中为名称)的任何信息(您可以在 Redis 框上的服务器端 Lua 中完成这整个事情,以更快地运行并避免网络返回- 来回,如果你愿意):

and then loop through the results and return whatever info on each (name in our example) in your language of choice (you can do this whole thing in server-side Lua on the Redis box to go even faster and avoid network back-and-forth, if you want):

for id in results:
    HGET id 'name'

你在这里的成本将是 O(m) 其中 m 是给定电话号码的用户数量,这将是一个非常快的操作Redis 因为它对速度进行了优化.在您的情况下这将是矫枉过正,因为您可能不需要这么快的事情,而且您更喜欢灵活的搜索,但这就是您的方式.

You're cost here will be O(m) where m is the number of users with the given phone number, and this will be a very fast operation on Redis because of how optimized it is for speed. It'll be overkill in your case because you probably don't need things to go so fast, and you'd prefer having flexible search, but this is how you would do it.

这篇关于搜索redis db的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆