小谈Redis JSON 系列一
写在前面的话
本文是笔者自己查询所能搜到的文档、视频资料整理所得,因原材料均为英文(具体材料见文章最后的参考文档),所以存在理解误差在所难免,欢迎大家进行探讨,并指出我的错误。
JSON
是一个轻量级的数据交换格式,我所在的公司前后端便是通过JSON
这种数据格式进行信息交互的。
Redis
也是软件开发提高性能必不可少的中间件。
那么将JSON
形式的数据放入Redis
数据库中也是不可避免的操作。
这是系列第一篇,主要通过Redis
对JSON
的传统操作,从而引出Redis JSON
这个本文的主角。
下面首先会讲一下,在Redis
中传统操作JSON
数据的两种方式。
Redis操作JSON的传统办法
Raw String 纯字符串
将JSON
数据,以string
的方式放入Redis
中。
使用方法
# 放置JSON
> set tag '{"1":{"tag":"GOAL_SELECT_TAG","execTs":1640676319},"2":{"tag":"GOAL_SELECT_TAG","execTs":1640676319}}'
OK
# 获取JSON
> get tag
{"1":{"tag":"GOAL_SELECT_TAG","execTs":1640676319},"2":{"tag":"GOAL_SELECT_TAG","execTs":1640676319}}
优点
- 占用内存小
缺点
JSON
数据中键级别的访问和修改是不支持的。采用string
形式,只能全量获取
Hash 数据结构
将JSON
数据使用HASH
的形式放入Redis
中。
使用方法
# 放置JSON
> hset h name zm age 16
2
# 获取JSON
> hgetall h
name
zm
age
16
> hget h name
zm
优点
- 提供
JSON
键级别的访问和修改,并且时间复杂度为O(1)
缺点
JSON
键的值只能为字符串或者数值,也就是说采用HASH
的方式存储,JSON
数据只能有一级,不能嵌套。比如
{
"1": {
"tag": "GOAL_SELECT_TAG",
"execTs": 1640676319
},
"2": {
"tag": "GOAL_SELECT_TAG",
"execTs": 1640676319
}
}
- 占用内存较
string
大
Redis JSON
Redis JSON
是Redis Modules
中的一个。
Redis Module
Redis JSON
就像Redis
的其他数据类型一样,
Redis JSON
新增了一种类型,且该类型在树的节点中以二进制的方式存储数据(ReJSON stores the data in binary format in the tree’s nodes
)。具体详见下面的实操。Redis JSON
提供了一系列API
来操作JSON 数据
。
Redis JSON启动与上手
操作环境搭建
- 先去redis cloud上注册,申请免费的数据库,并且添加
Redis JSON
以及Redis Search
两个Modules
。 - 根据上述生成的数据库配置项,采用终端或者客户端软件连接该
Redis
。 这样,我们就可以进行Redis JSON
的操作。
与此同时,发现的两个bug
-
Redis Cloud
中的拼写错误 -
Red
客户端的错误
一个Redis JSON
命令的样例
JSON.SET key $ '{"foo":"bar", "ans": 42}'
JSON.SET
:设置JSON
的命令。Redis JSON
的所有命令都需要带有JSON前缀key
:具体的key
名- $ :表示根路径。为了获取
JSON
中不同层级的键值,JSON
有自己的一套查询语言,详见JSONPath '{"foo":"bar", "ans": 42}'
:JSON字符串
由此可见,Redis JSON
的命令与普通Redis
命令的差异之处在于有一个Path
的说法,Path
就是为了方便且统一的解析JSON
数据(虽然现在并没有统一...)
There are at least two standards for JSON paths ...which means there is no standard for JSON paths.
Redis JSON 命令
常见命令演示
首先给定一个JSON
数据
{
"1": {
"tag": "GOAL_SELECT_TAG",
"execTs": 1640676319
},
"2": {
"tag": "GOAL_SELECT_TAG",
"execTs": 1640676319
}
}
- 设置
JSON
2022-01-10 20:22:44 JSON.SET tag $ '{"1":{"tag":"GOAL_SELECT_TAG","execTs":1640676319},"2":{"tag":"GOAL_SELECT_TAG","execTs":1640676319}}'
OK
- 获取键为
1
的内容
2022-01-11 21:37:36 JSON.GET tag $.1
[{"tag":"GOAL_SELECT_TAG","execTs":1640676319}]
- 获取键为
2
的tag
内容
2022-01-11 21:38:45 JSON.GET tag $.2.tag
["GOAL_SELECT_TAG"]
- 遍历获取
tag
值,返回数组
2022-01-10 20:23:01 JSON.GET tag $..tag
["GOAL_SELECT_TAG","GOAL_SELECT_TAG"]
- 增加或者减少键为
1
的execTs
数值
// 获取
2022-01-12 18:34:49 JSON.GET tag $.1
[{"tag":"GOAL_SELECT_TAG","execTs":1640676980}]
// 减少980
2022-01-12 18:35:00 JSON.NUMINCRBY tag $.1.execTs -980
// 最新的结果
[1640676000]
命令总结
- 对应
JSON
的不同组成部分Redis JSON
提供相应的命令 - 根据命令名称便能对其功能猜测一二,根据具体的需求各取所需,到时候参考官方文档即可。
总结
Redis JSON
是为了能够操作JSON
数据而存在的。- 命令的使用与普通
Redis
命令的差异之处在于Path
的概念。 - 为了更好的操作
JSON
数据,Path
是不可避免的。可以学习一下JSONPath的使用。 - 对于一个
Redis
命令来说,重要的除了功能之外,最重要的是命令对应的时间复杂度。但是其官方文档对其语焉不详,故本文为多做阐释,以免贻误大家。
这是Redis JSON
的第一篇文章,下面会可能就在实际项目中、命令时间复杂度、整体性能等方面进行撰文阐释,敬请期待。
参考文档
RedisJSON — Manipulando JSON como tipo nativo no Redis
JSON in Redis - When to use RedisJSON
RedisJSON + RediSearch as a real-time document database, Redis Labs
转载自:https://juejin.cn/post/7052271318598680613