点 快速的未来即将在您所在城市的活动中到来。

在 Redis Released 上加入我们

如何无中断运行 Redis SQL 查询

相关的电子书下载:内存内 NoSQL 数据库的重要性

运行 Redis SQL 查询 并不难。事实上,几年前,我与一位在零售公司管理数据仓库解决方案的朋友交谈时,提出了这一点。他解释了他面临的一个问题后,我们开始讨论 Redis 的查询。

我们的数据仓库解决方案存在一个痛点。我们有需要实时记录数据和执行分析操作的用例。然而,有时获取结果需要几分钟的时间。Redis 在这里能提供帮助吗?请记住,我们不能一次性淘汰和替换我们基于 SQL 的解决方案。我们只能一次跨一小步。

现在,如果你和我朋友的情况一样,我们有一个好消息要告诉你。你可以多种方式运行 Redis 查询,并在破坏当前基于 SQL 的解决方案的情况下将 Redis 引入架构。 

我们来探讨一下你可以如何做到这一点。不过在进一步了解之前,我们有一位 Redis 黑客马拉松选手开发了一款自己的应用,可让你用 SQL 查询 Redis 中的数据。 

观看下面的视频。

https://www.youtube.com/embed/ipmP_auUF0w

将表重新建模为 Redis 数据结构

将表映射到 Redis 数据结构 非常简单。要遵循的最有用的数据结构是: 

  • 哈希表
  • 有序集合
  • 集合

可以执行的一种操作是将每一行都存储为一个哈希表,其中密钥基于表的主键,并将密钥存储在集合或有序集合中。

图 1 显示了一个示例,说明如何将表映射到 Redis 数据结构。在此示例中,我们有一个名为 Products 的表。每一行都映射到一个哈希表数据结构。

主键 ID 为 10001 的行将作为密钥 product:10001 存储到哈希表中。在此示例中,我们有两个有序集合:第一个有序集合按主键遍历数据集,第二个有序集合按价格进行查询。

图 1. 将表映射到 Redis 数据结构


使用此选项,你需要更改代码,以使用 Redis 查询来代替 SQL 命令。以下是 SQL 和等效 Redis 命令的一些示例

A. 插入数据

SQL:
insert into Products (id, name, description, price)
values = (10200, “ZXYW”,“Description for ZXYW”, 300);
Redis:
MULTI
HMSET product:10200 name ZXYW desc “Description for ZXYW” price 300
ZADD product_list 10200 product:10200
ZADD product_price 300 product:10200
EXEC

B. 按产品 ID 查询

SQL:
select * from Products where id = 10200
Redis:
HGETALL product:10200

C. 按价格查询

SQL:
select * from Product where price < 300
Redis: 
ZRANGEBYSCORE product_price 0 300 

这会返回以下密钥:product:10001、product:10002、product:10003。现在针对每个密钥运行 HGETALL。

HGETALL product:10001
HGETALL product:10002
HGETALL product:10003

使用数据框将表自动映射到 Redis 数据结构

现在,如果你想在解决方案中保留 SQL 接口,并仅将基础数据存储更改为 Redis 以提升速度,那么你可以使用 Apache Spark 和 Spark-Redis 库进行更改。

Spark-Redis 库允许你使用 DataFrame API 存储和访问 Redis 数据。换句话说,你可以使用 SQL 命令插入、更新和查询数据,但数据在内部会映射到 Redis 数据结构。

图 2. Spark SQL 和 Redis 的堆栈

首先,您需要下载 spark-redis 并构建库以获取 jar 文件。例如,使用 spark-redis 2.3.1,您可以获取 spark-redis-2.3.1-SNAPSHOT-jar-with-dependencies.jar。

随后,您必须确保运行了 Redis 实例。 在我们的示例中,我们将在 localhost 和默认端口 6379 上运行 Redis。
您还可以在 Apache Spark 引擎上运行查询。以下是执行此操作的示例

$ spark-shell --jars spark-redis-2.3.1-SNAPSHOT-jar-with-dependencies.jar
scala> import org.apache.spark.sql.SparkSession

scala> val spark = SparkSession
.builder()
.appName("redis-sql")
.master("local[*]")
.config("spark.redis.host","localhost")
.config("spark.redis.port","6379").getOrCreate()

scala> import spark.sql

scala> import spark.implicits._

scala> sql("create table if not exists products(id string, name string, description string, price int) using org.apache.spark.sql.redis options (table 'product')")

scala> sql("insert into products values = ('10200','ZXYW','Description of ZXYW', 300)")

scala> val results = sql("select * from products")

scala> results.show()
+-----+----+-------------------+-----+
| id|name| description|price|
+-----+----+-------------------+-----+
|10200|ZXYW|Description of ZXYW| 300|
+-----+----+-------------------+-----+

现在,您还可以使用 Redis 客户端以 Redis 数据结构的形式访问此数据

127.0.0.1:6379> keys product*
1) "product:2e3f8611dbe94a588706a2aaea547caa"

更为有效的方法是使用 scan 命令,因为它允许您在浏览数据时分页。

127.0.0.1:6379> scan 0 match product*
1) "3"
2) 1) "product:2e3f8611dbe94a588706a2aaea547caa"
127.0.0.1:6379> hgetall product:2e3f8611dbe94a588706a2aaea547caa
1) "name"
2) "ZXYW"
3) "price"
4) "300"
5) "description"
6) "Description of ZXYW"
7) "id"
8) "10200"

现在,我们可以看到,这里有两种简单的方法可以在不中断的情况下运行 Redis SQL 查询。更进一步,您可能希望在我们的新白皮书中了解SQL Server 为何需要 Redis

但是,关于 Redis 中的实时数据,这只是您可以使用它提供实时体验的众多方式之一。 

如果您想了解 Redis 如何保证实时数据传输,请务必与我们联系