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

标签 redis relational-database

我一直在研究与关系数据库相比的 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/

相关文章:

node.js - 如何给集合命名(当我们映射多对多关系时自动生成)?

mysql - 为通常与可能值表相关的字段存储自定义值的最佳或最可接受的方法是什么?

php - MYSQL/PDO PHP系统---寻找大笔画输入

redis - 与 redis 的连接超时

database - 将 Redis 与 Node.js 前端+后端一起使用

linux - Redis 服务器可以处理多少个并发读取调用?

mysql - RDBMS 一对一关系以实现更高效的查找?

insert - 在redis中获取插入的键

laravel - 在 Laravel 中获取两个 Redis 集的交集

sqlite - 非常基本的 SQLite 表设计