IT评测·应用市场-qidao123.com

标题: 【redis】变乱 [打印本页]

作者: 悠扬随风    时间: 2025-3-14 21:51
标题: 【redis】变乱
简单地说,变乱表示一组动作,要么全部实行,要么全部不实行。Redis变乱是一组命令的聚集,通过MULTI、EXEC等命令实现批量操纵的原子性实行。
Redis变乱的特点

其核心特点包括:

   留意:Redis变乱差异于传统数据库变乱,它更雷同于命令批处理机制。
  Redis变乱的本质

命令队列机制

通过三个阶段实现变乱:
单线程保障

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客户端活动


原子性保障


实行流程对比

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

适用场景


组合优化方案

可将变乱与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()  # 单次网络请求完成事务
复制代码
特殊留意事项

变乱的范围性:

Pipeline的风险点:

选型建议

指标选择变乱选择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企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 IT评测·应用市场-qidao123.com (https://dis.qidao123.com/) Powered by Discuz! X3.4