学习以 JSON 格式存储、读取和搜索会话
最后更新时间:2024 年 4 月 23 日
目标
了解如何使用 JSON 数据类型对存储在 Redis 中的会话进行建模。
解决方案
Redis 提供了许多选项来有效地存储和检索数据;传统上,生态系统利用字符串和哈希数据类型。但是,会话存储不同类型的数据:元数据、列表、地理位置和整个对象。在高并发环境中找到正确的数据结构、使用低复杂度的数据访问模式以及管理会话过期可能会很困难。本文档将介绍使用 JSON 数据类型实现稳健的会话数据管理策略的想法。哈希和 JSON 数据结构可以在适当转换后存储对象,但 JSON 是存储多个嵌套对象的自然选择。JSON 在索引和搜索方面也更加灵活。
考虑以下会话数据,它存储会话元数据、购物车、已访问网站列表和位置。
{
"lastAccessedTime":1673354843,
"creationTime":1673354843,
"cart":[
{
"itemId":"hp-2341",
"itemCost":1990.99,
"quantity":3
},
{
"itemId":"MacBook",
"itemCost":2990.99,
"quantity":15
}
],
"location":"34.638,31.79",
["www.redis.com","www.google.com"]
}
Redis 可以有效地管理 JSON 文档并支持搜索。让我们考虑以下两个会话示例,其中包含一些用户数据。
JSON.SET session:a30d0c64-4cad-4088-a9ef-f1889d182df4 $ '{"lastAccessedTime":1672475765650,"creationTime":1672475765649,"user":{"name":"John","last":"Doe"},"visited":["www.redis.io","www.mortensi.com"], "location": "34.638,31.79", "cart":[{"itemId":"hp-2341","itemCost":1990.99,"quantity":2},{"itemId":"MacBook","itemCost":2990.99,"quantity":1}]}'
JSON.SET session:18920ac6-a2f0-4019-8250-e0036d17d015 $ '{"lastAccessedTime":1672475765645,"creationTime":1672475765549,"user":{"name":"Jane","last":"Appleseed"},"visited":["www.redis.io","www.microsoft.com"], "location": "35.178,31.768", "cart":[{"itemId": "invicta-jolly","itemCost":68.99,"quantity":1},{"itemId":"MacBook","itemCost":2990.99,"quantity":1}]}'
Redis 支持 JSON 文档的二级索引。我们可以按如下方式索引会话
NUMERIC SORTABLE
用于lastAccessedTime
和creationTime
TAG
用于已访问 URL 的集合TAG
用于 itemIdGEO
用于用户的地理位置
使用FT.CREATE 创建索引的语法如下
FT.CREATE session_idx ON JSON PREFIX 1 session: SCHEMA $.lastAccessedTime AS lastAccessedTime NUMERIC SORTABLE $.creationTime AS creationTime NUMERIC SORTABLE $.visited[*] AS visited TAG $.cart[*].itemId AS itemid TAG $.location AS loc GEO
验证索引是否已创建以及是否已索引两个文档:检查
FT.INFO session_idx
的输出,并查找num_docs
的值。
现在,我们可以使用该索引并在我们的会话中执行搜索。返回包含购物篮中 MacBook 的所有会话的搜索
FT.SEARCH session_idx '@itemid:{MacBook}' RETURN 0
1) (integer) 2
2) "session:a30d0c64-4cad-4088-a9ef-f1889d182df4"
3) "session:18920ac6-a2f0-4019-8250-e0036d17d015"
检查单个购物篮中是否存在产品的搜索(使用JSONPath 语法)
JSON.GET session:a30d0c64-4cad-4088-a9ef-f1889d182df4 '$.cart[?(@.itemId=="MacBook")]'
"[{\"itemId\":\"MacBook\",\"itemCost\":2990.99,\"quantity\":1}]"
获取接近给定位置(半径为 40 公里)的会话的搜索,利用
FT.SEARCH session_idx '@loc:[34.5 31.5 40 km]' return 0
1) (integer) 1
2) "session:a30d0c64-4cad-4088-a9ef-f1889d182df4"
返回最近创建的会话的搜索
FT.SEARCH session_idx "@creationTime:[-inf, +inf]" RETURN 1 creationTime LIMIT 0 1 SORTBY creationTime DESC
1) (integer) 2
2) "session:a30d0c64-4cad-4088-a9ef-f1889d182df4"
3) 1) "creationTime"
2) "1672475765649"
在这些需要紧凑的会话表示来表示集合、对象和地理位置,以及执行有效的会话内和跨会话查询和搜索的用例中,建议使用 JSON 数据类型作为有效且性能优良的解决方案。
参考
详细了解 Redis 的 JSON 支持