前言
redis 官方博客提供了一篇压测报告, 如下图所示:
按照压测报告所述,在隔离写入场景下,RedisJSON 比 MongoDB 快 5.4 倍,比 ElasticSearch 快 200 倍以上。隔离读取场景下,RedisJSON 比 MongoDB 快 12.7 倍,比 ElasticSearch 快 500 倍以上。
接下来,本文将通过实际案例带大家熟悉下这个神器。
RedisJson
RedisJSON 模块为 Redis 提供 JSON 支持。RedisJSON 允许您在 Redis 数据库中存储、更新和检索 JSON 值,类似于任何其他 Redis 数据类型。RedisJSON 还可以与 RediSearch 无缝协作,让您索引和查询 JSON 文档。
主要特点:
- 完全支持 JSON 标准
- 用于选择/更新文档中元素的 JSONPath 语法
- 文档以二进制数据形式存储在树结构中,允许快速访问子元素
- 支持对类型为 JSON 值的原子化操作
安装
- 浏览器打开下载地址, 选择版本并下载。
- 编译
确保服务器上已安装了如下依赖包:
sudo apt install build-essential llvm cmake libclang1 libclang-dev cargo
加压下载的源码,执行编译
make
或者
cargo build --release
编译成功,在 target/release 下有 librejson 模块文件。
- 启动加载
注意:Redis 版本需在 v6.0 版本以上。
建议在启动期间通过向 redis.conf 文件添加以下内容来加载 Redis 加载模块:
loadmodule /path/to/module/target/release/librejson.so `` ` 或者命令行启动方式: ```cmd redis-server --loadmodule {path}/target/release/librejson.so
基本使用
要了解如何使用 RedisJSON,最好从 Redis CLI 开始。
首先以交互模式启动 redis-cli, 并连接到 redis 服务器。
JSON.SET
命令用于给一个 key 设置一个 JSON 数据。JSON.SET
接受所有 JSON 值类型。本例创建了一个 JSON 字符串:
JSON.SET myKey $'{"user":{"name":"li","gender":"male"}}' "OK" JSON.GET myKey $ "{\"user\":{\"name\":\"li\",\"gender\":\"male\"}}"
指的是在哪个路径下添加。上述例子说明是在 下添加的,此处表述是根节点,如果想在 user 路径下再添加 json,可以这么写。
JSON.SET myKey $.user.job '{"type":"student"}'
下面是一些其他字符串操作。JSON.STRLEN 会告诉您字符串的长度,您可以使用 JSON.STRAPPEND 将另一个字符串附加到该字符串。
JSON.STRLEN myKey $ 1) "38"
数字可以递增和乘以:
JSON.SET num $ 0 OK JSON.NUMINCRBY num $ 1 "[1]" JSON.NUMINCRBY num $ 1.5 "[2.5]" JSON.NUMINCRBY num $ -0.75 "[1.75]" JSON.NUMMULTBY num $ 24 "[42]"
JSON.DEL
命令将删除使用 path 参数指定的任何 JSON 值。
您可以使用 RedisJSON 命令的专用子集操作数组:
JSON.SET arr $ [] OK JSON.ARRAPPEND arr $ 0 1) (integer) 1 JSON.GET arr $ "[[0]]" JSON.ARRINSERT arr $ 0 -2 -1 1) (integer) 3 JSON.GET arr $ "[[-2,-1,0]]" JSON.ARRTRIM arr $ 1 1 1) (integer) 1 JSON.GET arr $ "[[-1]]" JSON.ARRPOP arr $ 1) "-1" JSON.ARRPOP arr $ 1) (nil)
JSON 对象也有自己的命令:
JSON.SET obj $ '{"name":"Leonard Cohen","lastSeen":1478476800,"loggedOut": true}' OK JSON.OBJLEN obj $ 1) (integer) 3 JSON.OBJKEYS obj $ 1) 1) "name" 2) "lastSeen" 3) "loggedOut"
要以更易于阅读的格式返回 JSON 响应,请在原始输出模式下运行 redis-cli,并在 JSON 中包含格式关键字(如缩进、换行符和空格)。
redis-cli --raw JSON.GET obj INDENT "\t" NEWLINE "\n" SPACE " " $
[ { "name": "Leonard Cohen", "lastSeen": 1478476800, "loggedOut": true } ]
更详细的命令说明可以参考官方文档(https://redis.io/commands/?group=json)。
Java 操作 RedisJson
支持 RedisJson 命令的客户端有 Jedis、JRedisJSON、redis-modules-java 以及 redis-om-spring,一般采用 Jedis 进行操作。
maven
<dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>4.0.0</version> </dependency>
操作 json 对象
public class RedisJsonTest { @Test public void jsonTest(){ // 获取连接 HostAndPort config = new HostAndPort("127.0.0.1", 6379); PooledConnectionProvider provider = new PooledConnectionProvider(config); UnifiedJedis client = new UnifiedJedis(provider); IntStream.range(1,10).boxed().forEach(i -> { Apple apple = new Apple("a" + i, i); // 添加json client.jsonSet("apple:" + i, redis.clients.jedis.json.Path.ROOT_PATH,apple); }); // 删除索引 client.ftDropIndex("apple-index"); // 创建索引 // 创建要索引的字段 Schema schema = new Schema(). addTextField("$.name",1.0). addTextField("$.size", 1.0); // 只索引key以apple:开头的 IndexDefinition rule = new IndexDefinition(IndexDefinition.Type.JSON).setPrefixes("apple:"); // 创建索引 client.ftCreate("apple-index",IndexOptions.defaultOptions().setDefinition(rule),schema); // 查询字符串需要转义 Query q = new Query("@\\$\\.name:a*"). highlightFields(new Query.HighlightTags("<b>","</b>"),"$.name"). returnFields("$.name","$.size").limit(1,10); SearchResult searchResult = client.ftSearch("apple-index", q); List<Document> documents = searchResult.getDocuments(); for(Document document : documents){ Console.log(JSONUtil.toJsonStr(document)); } } }
小结
Redis JSON 是为了能够操作 JSON 数据而存在的。命令的使用与普通 Redis 命令的差异之处在于 Path 的概念。为了更好的操作 JSON 数据,Path 是不可避免的。有需要可以学习一下 JSONPath 的使用。关于 JSONPath 可以参考JsonPath(https://goessner.net/articles/JsonPath/)。