小编典典

搜索Redis数据库的值

redis

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

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

让我们以一个用例为例:我们需要存储大约大约200位个人数据。100.000人,这些数据需要通过姓名(电话:nr)进行搜索。

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

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)
运行时并不理想。

此外 ,这将使用比必要更多的空间,并且 KEY命令会降低访问性能。
http://redis.io/commands/keys

应该如何以正确的方式完成?我也可以想象ids会放在ZSET中,而需要搜索的数据可能就是分数,但这只能使范围与Serache无关。

提前也谢谢你,塔马斯

答案总结: 实际上,两个响应都表明Redis并非旨在搜索键的值。如果有必要使用此用例,则 需要实施解决方法
,如我的原始解决方案或以下解决方案所示。

与我最初的 解决方案相比,Eli 的以下 解决方案具有更好的性能 ,因为对键的访问可以视为恒定的,只需要遍历id的列表,这种访问将给
O(const) 运行时。此数据模型还允许一个人可能具有与其他人相同的电话号码,等等,例如姓名等。因此, 也可以建立1-n关系
(我会说旧的ERD术语)。

该解决方案的缺点在于, 它比我的我的 电话号码 占用更多的空间 ,而仅 搜索 起始数字的 电话号码
无法搜索

感谢您的两个回复。


阅读 328

收藏
2020-06-20

共1个答案

小编典典

Redis适用于需要以很高的频率访问和更新数据并且可以从数据结构(哈希,集,列表,字符串或排序集)的使用中受益的用例。它可以满足非常具体的用例。如果您有一个非常灵活的搜索之类的通用用例,那么为此目的而构建的某种东西(例如elasticsearch或SOLR)会更好地为您服务。

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

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具有用户想要的所有信息。例如,在搜索电话时,您将执行以下操作:

HGETALL 'phone:123-456-7891'

然后遍历结果,并以您选择的语言返回每个信息(在本示例中为名称)的任何信息(您可以在Redis框上的服务器端Lua中完成整个操作,以更快地进行操作并避免网络往返第四,如果您愿意):

for id in results:
    HGET id 'name'

您需要付出的代价是,拥有给定电话号码的用户数量在O(m)哪里m,由于对速度的优化,这将是对Redis的非常快速的操作。在您的情况下,这可能会适得其反,因为您可能不需要这么快的时间,并且您希望进行灵活的搜索,但这就是您要这样做的方式。

2020-06-20