使用 Redis 作为键值存储

Jey*_*eyJ 4 json redis

我正在测试 Redis 是否可以成为键值存储的良好解决方案。就我而言,租户的用户可以在我们的系统中保存键值对。数据如下所示:

{
"user" : "x1",
"tenant" : "y1",
"key": "key1",
"value": "value1",
"last_updated": "xxx-xx-xxx"
"another-metadata-field": "ddd"
}
Run Code Online (Sandbox Code Playgroud)

我的主要目标是:

  1. 根据用户和租户快速查询key1的值(select value from table where user=x and tenant=y and key=z)。
  2. 快速存储用户和租户的键值对。
  3. 检索特定用户/租户的所有键值对和元数据(last_updated..)(可能慢约 2 秒)(select * from table where user=x and tenant=yselect * from table where tenant=z

我可以使用 RDBMS 来做到这一点,但我想它会比使用内存数据库(持久性)慢。

对于 Redis,我考虑通过以下方式保存数据(使用本机 Redis 类型):

127.0.0.1:6379> sadd tenant1 user1
(integer) 1
127.0.0.1:6379> sadd tenant1 user2
(integer) 1
127.0.0.1:6379> sadd tenant1_user1 key1
(integer) 1
127.0.0.1:6379> sadd tenant1_user1 key2
(integer) 1
127.0.0.1:6379> hset "tenant1:user1:key1" value 50
(integer) 1
127.0.0.1:6379> hset "tenant1:user1:key1" last_updated "xx-xx-xxxx"
(integer) 1
127.0.0.1:6379> hget "tenant1:user1:key1" value
"50"
Run Code Online (Sandbox Code Playgroud)

通过这种方法,我可以快速检索特定的密钥,但为了检索特定用户/租户的所有键值,我需要执行如下操作:

// Get all key-values of specific user and tenant
smembers tenant1_user1
1) "key1"
2) "key2"

hgetall "tenant1:user1:key1"
1) "value"
2) "50"
3) "last_updated"
4) "xx-xx-xxxx"

// Get all key-value pairs of tenant
127.0.0.1:6379> smembers tenant1
1) "user2"
2) "user1"
127.0.0.1:6379> smembers tenant1_user1
1) "key1"
2) "key2"
127.0.0.1:6379> hgetall "tenant1:user1:key1"
1) "value"
2) "50"
3) "last_updated"
4) "xx-xx-xxxx"
Run Code Online (Sandbox Code Playgroud)

我想知道 :

  1. 这是在这个用例中实现的 redis 方式吗?

  2. 如果值为 json,则将 json 保存为字符串在内存利用率方面似乎是一个错误的决定。redis-json 适合这里吗?

Sim*_*ett 5

在我看来你走在正确的道路上。通过使用哈希和集合的方法,您可以相对轻松地进行一些性能改进......

HSET是可变参数,因此您可以一次设置多个属性,从而节省网络往返时间:

HSET "tenant1:user1:key1" value 50 last_updated "xx-xx-xxxx"
Run Code Online (Sandbox Code Playgroud)

您可以使用 Lua 脚本 ( https://redis.io/docs/interact/programmability/eval-intro/ ) 使使用集合和哈希值的查找作为原子操作在 Redis 服务器上执行。如果您使用的是 Redis 7 ( https://redis.io/docs/interact/programmability/functions-intro/ ),请考虑使用函数。这允许您在服务器上执行循环和分支/条件逻辑。

如果您有权访问 Redis Stack ( https://redis.io/docs/getting-started/install-stack/ ) - 请注意,它的许可方式不同,但对于大多数用例来说仍然是免费的 ( https://redis. io/docs/about/license/),那么您可以使用搜索功能。您将继续将数据存储在哈希中(或在 Redis Stack 中使用 JSON 文档,因为它将 JSON 添加为本机数据类型)。然后使用该FT.CREATE命令在数据集上创建索引,描述要索引的字段。然后,Redis 将为您跟踪数据的更改并自动更新索引,而您的应用程序无需维护额外的数据结构(例如集合)。

然后,您可以使用该FT.SEARCH命令执行类似 SQL 的查询。这是一个相当大的话题,如果您决定走 Redis Stack 路线,Redis 大学有涵盖这些概念的课程:

你还问过:

如果值为 json,则将 json 保存为字符串在内存利用率方面似乎是一个错误的决定。redis-json 适合这里吗?

将 JSON 序列化为 Redis 字符串(例如将其存储为哈希中的字段)的成本很高,因为您需要将所有 JSON 发送到 Redis 或从 Redis 发送所有 JSON 才能读取其中的任何内容,并且无法自动更新它。如果您有权访问 Redis Stack,则使用 JSON 数据类型可以显着减少客户端和服务器之间不必要的数据移动,并以原子方式对 Redis 中的 JSON 文档执行各种操作。