Redis可以处理这个简单的查询

时间:2014-12-18 09:05:37

标签: redis relational-database

与关系数据库相比,我一直在调查 Redis 功能,而不会遇到NFR问题,例如响应时间,可扩展性等,我了解Redis的优秀。

以下是Redis可以为Web应用程序处理的list of use-cases
提到这一点,Redis的一个已知缺点是进行业务分析,但分析应该有多复杂,以使Redis在与MySQL比较时效率较低?

例如,如果MySQL中有以下数据结构:
表格:用户列: ID(PK),名称(VarChar),年龄(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 存储上面的Datastructure,并以与MySQL相同(或更高)的效率查询它吗?

1 个答案:

答案 0 :(得分:7)

简答:是的。

答案很长:Redis是一项了不起的技术,但它不是关系型数据库。包含Redis的NoSQL构建在需要根据与其一起使用的访问模式存储数据的前提下。因此,要完成上述操作,您首先必须“正确”存储数据。

要存储表格的行,您似乎想要使用哈希数据结构。在Redis的术语中,以下是如何为UserID 123创建用户密钥:

HMSET user:123 id 123 name foo age 31

注1:在构造密钥名称时使用冒号(':')仅仅是一种约定。
注2:虽然ID已经是密钥名称的一部分,但通常会在哈希中包含一个字段以便于访问。

同样,这里是你如何创建一个消息密钥(ID为987):

HMSET message:987 id 987 userid 123 content bar importance 3

现在有趣的部分:) Redis没有FK或索引,因此您必须维护数据结构,以帮助您根据您的要求获取数据。对于您的第一个查询,最好的选择是保留一个排序集,其中成员是消息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年的用户 - 同样,应使用相同的排序集技巧:

ZADD users_by_age 31 123
ZRANGEBYSCORE users_by_age (30 +inf

这将为您提供符合条件的所有用户的列表,但您还需要跟踪(索引)每个用户的所有邮件。为此,请使用Set:

SADD user:123:messages 987

要绑定所有内容,这是另一个伪代码段:

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脚本和更智能的索引可以轻松获得......如果您需要任何进一步的帮助,请问:)