我一直在研究与关系数据库相比的 Redis 功能,但没有涉及响应时间、可伸缩性等 NFR 问题,据我所知,Redis 在这些方面表现出色。
这里有一个例子 list of use-cases Redis 可以处理网络应用程序。
话虽如此,Redis 的一个已知缺点是无法进行业务分析,但分析应该有多复杂才能使 Redis 与 MySQL 等相比效率较低?
例如,如果在 MySQL 中有以下数据结构:
表:用户列: Id(PK), Name(VarChar), Age(Int)
表:消息列:用户ID(FK)、内容(VarChar)、重要性(Int)
在我的应用程序中,我想使用以下 2 个查询:
1. SELECT Content FROM Message WHERE Importance > 2;
2. SELECT Content FROM Message,Users WHERE User.Id=Message.UserID and
User.Age > 30;
我的问题:
我可以使用 Redis 来存储上面的数据结构并以与 MySQL 相同(或更高)的效率查询它吗?
最佳答案
简短的回答:是的。
长答案:Redis 是一项了不起的技术,但它不是关系数据库。包括 Redis 在内的 NoSQL 建立在数据需要根据与其一起使用的访问模式存储的前提下。因此,要完成上述任务,您首先必须“正确”存储数据。
要存储表格的行,您似乎需要使用散列数据结构。在 Redis 的术语中,以下是为 UserID 123 创建用户 key 的方法:
HMSET user:123 id 123 name foo age 31
注意 1:在构造 key 名称时使用冒号(“:”)只是一种约定。
注意 2:虽然 ID 已经是 key 名称的一部分,但通常将其包含在哈希中的一个字段以便于访问。
同样,下面是创建消息 key (ID 为 987)的方法:
HMSET message:987 id 987 userid 123 content bar importance 3
现在有趣的部分来了 :) Redis 没有 FK 或索引,因此您必须维护数据结构以帮助您根据需要获取数据。对于您的第一个查询,最好的选择是保留一个 Sorted Set,其中成员是消息 ID,分数是重要性。因此:
ZADD messages_by_importance 3 987
获取重要性大于 2 的消息内容将通过以下伪 Pythonic 代码所示的两个操作完成:
messages = r.zrangebyscore('messages_by_importance', '(2', '+inf')
for msg in messages:
content = r.hget('message:' + msg, 'content')
do_something(content)
注意 3:此代码段非常幼稚,可以对其进行优化以获得更好的性能,但它应该为您提供基本要点。
对于第二个查询,您首先需要找到 30 岁以上的用户 - 同样,应该使用相同的 Sorted Set 技巧:
ZADD users_by_age 31 123
ZRANGEBYSCORE users_by_age (30 +inf
这将为您提供符合条件的所有用户的列表,但您还需要跟踪(索引)每个用户的所有消息。为此,请使用一个集合:
SADD user:123:messages 987
为了绑定(bind)所有内容,这是另一个伪代码段:
users = r.zrangebyscore('users_by_age', '(30', '+inf')
for user in users:
messages = r.smembers('user:' + user + ':messages')
for msg in messages:
content = r.hget('message:' + msg, 'content')
do_something(content)
这应该足以让您入门,但是一旦您牢牢掌握了基础知识,就可以考虑优化这些流程。根据您的需要使用流水线、Lua 脚本和更智能的索引,您可以轻松获得 yield ……如果您需要任何进一步的帮助 - 只需询问 :)
关于redis - Redis 可以处理这个简单的查询吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27542756/