【redis】变乱

打印 上一主题 下一主题

主题 950|帖子 950|积分 2850

简单地说,变乱表示一组动作,要么全部实行,要么全部不实行。Redis变乱是一组命令的聚集,通过MULTI、EXEC等命令实现批量操纵的原子性实行。
Redis变乱的特点

其核心特点包括:


  • 序次性:命令按入队序次实行
  • 隔离性:单线程模型保证变乱实行不被打断
  • 弱原子性:不支持回滚机制(运行时错误不会中断后续命令)
  • 乐观锁支持:通过WATCH命令监控键值变革
   留意:Redis变乱差异于传统数据库变乱,它更雷同于命令批处理机制。
  Redis变乱的本质

命令队列机制

通过三个阶段实现变乱:

  • 开启变乱:MULTI命令创建命令队列
  • 命令入队:将操纵指令存入内存队列(不实行语法检查)
  • 实行变乱:EXEC触发队列命令的FIFO序次实行
单线程保障

Redis主线程依次实行变乱队列中的命令,保证:


  • 实行期间不会被其他客户端哀求打断
  • 天然实现隔离性(串行化实行)
Redis变乱命令使用

有关变乱类型的命令可以通过help @transactions命令来检察。有关命令的使用可以通过help 命令来检察,比方help exec。
  1. 127.0.0.1:6379> help @transactions
  2.   DISCARD -
  3.   summary: Discard all commands issued after MULTI
  4.   since: 2.0.0
  5.   EXEC -
  6.   summary: Execute all commands issued after MULTI
  7.   since: 1.2.0
  8.   MULTI -
  9.   summary: Mark the start of a transaction block
  10.   since: 1.2.0
  11.   UNWATCH -
  12.   summary: Forget about all watched keys
  13.   since: 2.2.0
  14.   WATCH key [key ...]
  15.   summary: Watch the given keys to determine execution of the MULTI/EXEC block
  16.   since: 2.2.0
复制代码
基础命令演示

变乱提交成功的演示:
  1. # 开启事务
  2. 127.0.0.1:6379> multi
  3. OK
  4. # 命令进入队列,并没有直接执行
  5. 127.0.0.1:6379(TX)> set xxoo ooxx
  6. QUEUED
  7. # 命令进入队列,并没有直接执行
  8. 127.0.0.1:6379(TX)> incr count
  9. QUEUED
  10. # 执行事务
  11. 127.0.0.1:6379(TX)> exec
  12. 1) OK
  13. 2) (integer) 1
复制代码
变乱取消的演示:
  1. # 开启事务
  2. 127.0.0.1:6379> multi
  3. OK
  4. # 命令进入队列,并没有直接执行
  5. 127.0.0.1:6379(TX)> set ooxx xxoo
  6. QUEUED
  7. # 命令进入队列,并没有直接执行
  8. 127.0.0.1:6379(TX)> incr count
  9. QUEUED
  10. # 取消事务
  11. 127.0.0.1:6379(TX)> discard
  12. OK
复制代码
高级用法:乐观锁

乐观锁获取锁成功的演示:
  1. 127.0.0.1:6379> set balance:Morris 1000
  2. OK
  3. # 监视账户余额,类似cas
  4. 127.0.0.1:6379> watch balance:Morris
  5. OK
  6. 127.0.0.1:6379> multi
  7. OK
  8. 127.0.0.1:6379(TX)> decrby balance:Morris 100
  9. QUEUED
  10. 127.0.0.1:6379(TX)> incrby balance:Bob 100
  11. QUEUED
  12. 127.0.0.1:6379(TX)> exec
  13. 1) (integer) 900
  14. 2) (integer) 100
复制代码
乐观锁获取锁失败的演示:
  1. 127.0.0.1:6379> set balance:Morris 1000
  2. OK
  3. 127.0.0.1:6379> watch balance:Morris
  4. OK
  5. 127.0.0.1:6379> multi
  6. OK
  7. 127.0.0.1:6379(TX)> decrby balance:Morris 100
  8. QUEUED
  9. 127.0.0.1:6379(TX)> incrby balance:Bob 100
  10. QUEUED
  11. # 此时balance:Morris被其他客户端修改,事务失败返回(nil)
  12. 127.0.0.1:6379(TX)> exec
  13. (nil)
复制代码
原子性缺陷演示

Redis在变乱实行时,如果在命令入队时就有语法错误,好比命令不存在或者参数错误,那么整个变乱会被拒绝实行,这时间是原子性的。但如果在实行过程中出现运行时错误,好比对字符串举行INCR操纵,这时间错误命令之后的命令还会继续实行,这样原子性就被粉碎了。
语法错误导致全体失败

  1. 127.0.0.1:6379> multi
  2. OK
  3. 127.0.0.1:6379(TX)> set k1 v1
  4. QUEUED
  5. # 命令不存在,语法错误
  6. 127.0.0.1:6379(TX)> xxx k1
  7. (error) ERR unknown command `xxx`, with args beginning with: `k1`,
  8. 127.0.0.1:6379(TX)> exec
  9. (error) EXECABORT Transaction discarded because of previous errors.
复制代码
原子性表现:若存在入队时即可检测的语法错误​(如命令不存在、参数错误),整个变乱会被拒绝实行,此时具有原子性。
运行时错误部分成功

  1. 127.0.0.1:6379> multi
  2. OK
  3. 127.0.0.1:6379(TX)> set k1 v1
  4. QUEUED
  5. # 类型错误(对字符串执行SADD)
  6. 127.0.0.1:6379(TX)> sadd k1 oo xx
  7. QUEUED
  8. 127.0.0.1:6379(TX)> set k2 v2
  9. QUEUED
  10. 127.0.0.1:6379(TX)> exec
  11. 1) OK
  12. 2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
  13. 3) OK
复制代码
原子性缺陷:变乱中运行时错误(如数据类型不匹配)不会影响后续命令实行,结果中前两条命令见效,第三条失败,导致部分成功
与传统数据库变乱对比

特性Redis变乱MySQL变乱原子性部分支持(无回滚机制)完全支持(UNDO日记回滚)隔离性天然隔离(单线程模型)通过锁机制实现多隔离级别持久性依赖AOF配置默认保证(redo日记)同等性需配合WATCH实现外键/约束自动保障实行机遇命令延迟实行及时实行 Pipeline和变乱的区别

服务端活动VS客户端活动



  • 变乱:是Redis服务端原生支持的原子操纵机制,通过MULTI开启变乱模式后,服务端会将后续命令存入队列缓存,直到实行EXEC时才一次性按序次实行全部命令。
  • Pipeline:本质是客户端批量发送命令的优化计谋,服务端无法区分平凡命令与Pipeline命令,仅作为一连的命令哀求处理。
原子性保障



  • 变乱:提供弱原子性保证,变乱队列中的命令在EXEC实行时会作为团体串行实行,但运行时错误(如类型操纵错误)不会中断后续命令
  • Pipeline:完全不具备原子性,命令可能被其他客户端的操纵打断,仅在命令量少(能被内核缓冲区容纳)时可能保持原子性
实行流程对比

特性变乱Pipeline命令实行机遇EXEC触发批量实行立刻发送到服务端网络交互次数MULTI+命令+EXEC共3次来回单次批量发送全部命令错误处理语法错误导致全体失败,运行时错误部分实行无特殊处理,按平凡命令逐条响应壅闭风险长变乱可能壅闭其他哀求无服务端壅闭风险 应用场景与优化计谋

适用场景



  • 变乱:需要简单原子性操纵的场景(如库存扣减、转账),配合WATCH实现乐观锁控制
  • Pipeline:批量非原子性操纵(如日记写入、数据预热),减少高并发场景下的网络开销
组合优化方案

可将变乱与Pipeline结合,减少变乱命令的网络传输时间:
  1. # 将MULTI/EXEC封装在Pipeline中
  2. pipe = redis.pipeline(transaction=True)
  3. pipe.multi()
  4. pipe.set('a', 1)
  5. pipe.incr('b')
  6. pipe.execute()  # 单次网络请求完成事务
复制代码
特殊留意事项

变乱的范围性:


  • 不支持回滚机制,需通过WATCH+重试计谋实现数据同等性
  • 变乱内不能实行壅闭命令(如BLPOP),否则会退化为平凡命令
Pipeline的风险点:


  • 大流量Pipeline可能触发服务端缓冲区溢出(需配置client-output-buffer-limit)
  • Cluster模式下需确保全部命令指向同一节点
选型建议

指标选择变乱选择Pipeline需要原子性✔️❌高吞吐量需求❌(变乱壅闭风险)✔️涉及跨键操纵✔️(配合WATCH)❌命令间存在逻辑依赖✔️(Lua脚本更优)❌   扩展方案:对于需要强原子性的复杂操纵,推荐使用Lua脚本替换变乱,可实现真正的原子性实行。
  1. -- Lua脚本原子扣减库存
  2. if redis.call('GET', KEYS[1]) >= ARGV[1] then
  3.     return redis.call('DECRBY', KEYS[1], ARGV[1])
  4. else
  5.     return -1
  6. end
复制代码
Java中使用Redis变乱

  1. package com.morris.redis.demo.transaction;
  2. import redis.clients.jedis.Jedis;
  3. import redis.clients.jedis.Transaction;
  4. import java.util.List;
  5. /**
  6. * jedis中事务的使用
  7. */
  8. public class JedisTransactionDemo {
  9.     public static void main(String[] args) {
  10.         try (Jedis jedis = new Jedis("localhost")) {
  11.             // 监控关键键
  12.             jedis.watch("balance:Morris");
  13.             Transaction tx = jedis.multi();
  14.             try {
  15.                 tx.decrBy("balance:Morris", 100);
  16.                 tx.incrBy("balance:Bob", 100);
  17.                 List<Object> results = tx.exec();  // 提交事务
  18.                 System.out.println("转账成功:" + results);
  19.             } catch (Exception e) {
  20.                 tx.discard();  // 放弃事务
  21.                 System.out.println("数据被修改,事务回滚");
  22.             } finally {
  23.                 jedis.unwatch();  // 解除监控
  24.             }
  25.         }
  26.     }
  27. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

悠扬随风

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表