批量执行Redis命令的四种方法 (批量执行redis)
前言
在我们的印象中,命令好像都是一个个单条进行执行的。如果有人问你如何批量执行Redis命令,你能回答的上吗?或者说能答出几种方式呢?最容易想到的是Redis的一些批量命令,例如MGET。今天我们就来总结一下!
Redis命令执行过程
在了解批量执行有哪些方式之前,我们简单回顾下Redis命令执行的过程:
为什么需要批量执行命令?
在了解批量执行命令有哪些方式之前,我们先简单整理下「批量执行命令」比「执行多个单Redis命令」能带来哪些好处!
- 减少网络开销
- 提高执行效率 (减少RTT)
批量执行命令的方式
批量执行命令的方式主要有以下四种:
- Redis原生命令 (例如MSET、HMGET、HMSET、SADD)
- Pipeline (管道)
- Lua脚本
- Redis事务
1. Redis原生命令
Redis的原生命令就支持批量命令的操作,比如:HMSET、HMGET、SADD。其中,MSET和HMGET用于批量获取或设置多个key的值,SADD用于批量向有序集合中添加多个元素。
- MSET:设置一个或多个指定key的值
- MGET:从一个或多个指定的key中获取值
MSET key1 value1 key2 value2 ...
MGET key1 key2 ...
- HMSET:设置多个字段及其值
- HMGET:获取多个字段的值
HMSET key field1 value1 field2 value2 ...
HMGET key field1 field2 ...
- SADD:向有序集合中添加多个元素
SADD key member1 member2 ...
2. Pipeline (管道)
Pipeline是Redis提供的另一种批量执行命令的方式。它允许客户端将多个命令放入一个管道中,然后一起发送给Redis服务器执行。这样可以减少网络开销,提高执行效率。Redis对于不同类型的命令和key会进行批量的优化,例如对于String类型的命令,会采用特定的数据结构进行优化,对于相同的key的命令,会进行批量的处理。
// 创建管道
const pipeline = redisClient.pipeline();
// 添加命令到管道
pipeline.get('key1');
pipeline.set('key2', 'value2');
pipeline.sadd('key3', 'member3');
// 执行管道中的所有命令
const results = await pipeline.exec();
3. Lua脚本
Lua脚本也可以用来批量执行Redis命令。Lua脚本可以将多个Redis命令组合成一个脚本,然后一起发送给Redis服务器执行。这可以进一步减少网络开销,提高执行效率。Lua脚本还支持条件执行、循环等高级功能。
// 创建Lua脚本
const script = `
return {
redis.call('get', KEYS[1]),
redis.call('set', KEYS[2], ARGV[1]),
redis.call('sadd', KEYS[3], ARGV[2])
}
`;
// 执行Lua脚本
const results = await redisClient.evalsha(script, 3, 'key1', 'key2', 'key3', 'value2', 'member3');
4. Redis事务
Redis事务可以保证一组命令要么全部执行成功,要么全部执行失败。这对于需要保证数据一致性的场景非常有用。Redis事务可以在Pipeline的基础上进行,但是提供了额外的原子性和隔离性保证。
// 开始事务
redisClient.multi();
// 添加命令到事务
redisClient.get('key1');
redisClient.set('key2', 'value2');
redisClient.sadd('key3', 'member3');
// 执行事务
const results = await redisClient.exec();
总结
批量执行Redis命令有以下几种方式:
- Redis原生命令
- Pipeline (管道)
- Lua脚本
- Redis事务
根据不同的场景,可以灵活选择最适合的批量执行方式。一般情况下,对于简单的批量命令操作,可以使用Redis原生命令。对于需要减少网络开销和提高执行效率的场景,可以使用Pipeline或Lua脚本。对于需要保证数据一致性的场景,可以使用Redis事务。
(15)redis Pipeline详解
redis客户端执行命令4个过程: 发送命令-〉命令排队-〉命令执行-〉返回结果 过程称为 Round trip time (简称RTT, 往返时间),mget mset有效节约RTT,但大部分命令(如hgetall,并没有mhgetall)不支持批量操作,需要 消耗N次RTT,pipeline解决 比逐条执行要快,特别是客户端与服务端的 网络延迟越大,体能越明显 原生批命令: 原子性 ,pipeline: 非原子性 原生批命令: 一命令多个keypipeline: 支持多命令(存在事务) 原生批命令: 服务端 实现,pipeline:服务端与客户端 共同完成 pipeline组装命令不能太多,不然数据量过大,增加客户端的等待时间,造成网络阻塞,可将 大量命令的拆分多个小pipeline命令: redis提供 mset 、 mget 方法,但没提供 mdel 方法,如想实现,可借助pipelinemset: 同时设置一个或多个 key-value 对。 redis 127.0.0.1:6379> MSET key1 value1 key2 value2 .. keyN valueN1)获取jedis对象 (一般从连接池中获取)2) 获取jedis对象 的pipeline对象 3)添加、执行指令 用pipeline提交所有操作并返回执行结果: 为了保证pipeline原子性,redis提供了简单的事务。 1、redis的简单事务 :放multi和exec命令之间,multi代表事务开始,exec代表事务结束 2、停止事务discard: 3、命令错误,语法不正确,导致 事务不能正常结束 4、运行错误,语法正确,但 类型错误,事务可以正常结束 5、watch命令:用watch后,multi失效,事务失效 WATCH机制: 事务EXEC执行时,Redis检查被WATCH的key,只有被WATCH的key从 WATCH起始时至今没有发生过变更,EXEC才会被执行 ,变化则失败。 小结:redis提供简单事务,不支持事务回滚
Redisson批量操作类RBuckets和管道利器RBatch
在SpringBoot项目中,通过RBuckets接口实现批量操作对个Bucket对象,示例如下: 方法介绍: 多个连续命令可以通过RBatch对象在一次网络会话请求里合并发送,这样省去了产生多个请求消耗的时间和资源。 这在Redis中叫做管道。 RBatch管道功能就是REDIS的批量发送,实际上是客户端的功能,与服务端无关。 相当于把多个请求的命令放在一个数据包通过TCP发送到服务端,然后客户端再一次性读取所有的命令回应。 管道技术最显著的优势是提高了 redis 服务的性能。 执行batchDemo()后,控制台打印结果如下: 测试用例主要介绍了Hash,当然RBatch还支持List、Set、对象桶、队列、发布订阅等。 顺便介绍一下Redis中Map的使用场景 在集群模式下,所有的命令会按各个槽所在的节点,筛选分配到各个节点并同时发送。 每个节点返回的结果将会汇总到最终的结果列表里。 上述demo中用到的工具类如下: 参考:
免责声明:本文转载或采集自网络,版权归原作者所有。本网站刊发此文旨在传递更多信息,并不代表本网赞同其观点和对其真实性负责。如涉及版权、内容等问题,请联系本网,我们将在第一时间删除。同时,本网站不对所刊发内容的准确性、真实性、完整性、及时性、原创性等进行保证,请读者仅作参考,并请自行核实相关内容。对于因使用或依赖本文内容所产生的任何直接或间接损失,本网站不承担任何责任。