| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 大数据 -> 19 事务 相关操作 -> 正文阅读 |
|
[大数据]19 事务 相关操作 |
前言相关介绍主要围绕着 redis?里面的事务相关特性? 如下常用的命令来自于我们常见的教程 :?Redis 事务 | 菜鸟教程? 本文的相关代码 拷贝自 redis-6.2.0?? 代码来自于?https://redis.io/? redis 事务机制redis 的事务机制相对来说实现的比较简单, 也和我们常见的 数据库的相关事务是存在的较大的差异? 执行方式大概是如下 : 先执行 multi 启动一个事务, 在执行 n 个 command[不会真正执行, 进入到队列], 可以执行 exec 批量执行这 n 个事务 或者 discard 丢弃这个事务? 我们这里主要是剖析如下四个场景? 1. multi + n 个正常的命令 + exec? 2. multi + m个参数正常的命令 + 1个参数不正常的命令 + n个参数正常的命令?+ exec 2. multi + m个参数正常的命令 + 1个参数正常的命令但是逻辑意义不正常[xxCommand会返回错误]?+ n个参数正常的命令?+ exec 4. multi + n 个正常的命令 + discard? 5. watch/unwatch?机制 1. multi + n 个正常的命令 + exec?执行效果大致是如下?
multi 的执行走的正常的命令的执行流程? 这里的主要业务是 更新 client 的 flags, 增加 事务标记? set name zzzz 的执行client 这边标记了处于 multi 执行 将 "set name zzzz" 添加到了?mstate.commands 里面, 返回给客户端 QUEUED? get name 的执行client 这边标记了处于 multi 执行 将 "get name" 添加到了?mstate.commands 里面, 返回给客户端 QUEUED? exec 的执行走的正常的命令的执行流程? 循环执行 mstate 里面的所有的命令? 2. multi + m个参数正常的命令 + 1个参数不正常的命令 + n个参数正常的命令?+ exec后面的这部分命令的执行, 我们就不会去再看 multi, 各个命令的执行, exec 的执行了? 我们主要会解释 到底执行了那些命令, 有哪些奇怪的问题, 造成的原因是什么 ?? 如下在执行第二个 set 的时候, 带了足够的参数, 但是这里的 "set name jerr1 df" 显然执行的时候是会存在问题的? 如下在执行第三个 set 的时候, 没有跟参数, 不符合参数数量的约束, redis 这里是直接把错误信息给客户端了? 但是最后执行 exec 的时候, 提示性信息是 "EXECABORT Transaction discarded because of previous errors."
在执行 第三个 "set" 的时候, 由于参数数量不符合期望, 走了 rejectCommandFormat? 这里面调用了 flagTransaction, 标记 事务为 dirty? 在执行 exec 的时候? 响应给客户端了 "EXECABORT Transaction discarded because of previous errors."? 并且丢弃了事务? 最终 exec 阶段是, 任何一个 事务里面 任何一个命令都没有执行? 3. multi + m个参数正常的命令 + 1个参数正常的命令但是逻辑意义不正常[xxCommand会返回错误]?+ n个参数正常的命令?+ exec初始的时候 name 为 zerry? 接着开启了一个事务? 第一条 set, 设置 name 为 jerry? 第二条 set, 显然是参数数量符合要求, 但是不满足 setCommand 的要求? 第三条 get, 获取 name? 最终执行结果为, 第二条 set 报错, name 为 jerry? 因此 是三条命令均执行了, 只是错误的命令不影响其他的命令的执行[参见上面 exec 的for]?
这个也很好解释?? multi 之后, 依次将 "set name jerry", "set name jerr1 df", "get name" 放入服务端维护的 client.mstate.commands?的队列? 然后 exec 依次执行?client.mstate.commands 里面的命令, 响应结果信息给客户端? 最终 exec 阶段是, 任何一个 事务里面 所有的一个命令都执行了? 4. multi + n 个正常的命令 + discard?multi 开启了一个事务? 接着添加了两个命令 "set name zzzz", “get name" 然后丢弃了事务?
discar 的执行?丢弃了事务, 并返回客户端 ok? 释放了 client.mstate 里面的保存的已经入队的命令信息? 重置了 client.mstate, client.flags? unwatchAllKeys? 5. watch/unwatch?机制watch 给定的 key, 如果给定的 key 在 exec 之前发生了改变, 则放弃执行? 如下执行序列, 在 exec 之前, 我再另外的一个 redis-cli 里面修改了 name 的值? 然后执行 exec, 发现 服务端返回的是 null, 怎么回事呢 ??
exec 经历了什么?我们来看一下 exec 执行的时候, 这里 flags 为 40[CLIENT_MULTI | CLIENT_DIRTY_CAS], 因此返回的是 null? 然后之后走的时候 丢弃事务[参见上面的 discard 的命令] 的流程? 接下来, 我们来看详细的一下 这波操作? watch name?注册了 key -> client?到 watchedKeys "key -> [client1, client2, ...?]" 里面? 注意这里 watchedKeys 存储了两个地方, 两个地方的逻辑意义是不一样的? client 里面存储了一份, 记录的是当前 client watch 了那些 [db, key]? db 里面存储了一份, 存储的是当前 db 里面 key -> [client1, client2, ...]? exec 之前, 另外一个 redis-cli 执行 set name o0o0o0当第另外个 redis-cli 更新 name 的时候, 发送了更新通知? 更新通知这边处理的其中一件事情就是 touchWatchedKey? 对于 name 这个 key, 第一个 redis-cli watch 这个 key, 将其 flags 增加 CLIENT_DIRTY_CAS 的标记? 再回到第一个 redis-cli 的 exec?执行 exec 的时候发现 flags 标记为?CLIENT_DIRTY_CAS? 返回给客户端 null, 并丢弃了事务? unwatch?前面跳到了 watchedKeys 在两个地方又维护? client 里面存储了一份, 记录的是当前 client watch 了那些 [db, key]? db 里面存储了一份, 存储的是当前 db 里面 key -> [client1, client2, ...]? 遍历当前 client 所维护的 watchedKeys, 从 db->watchedKeys 中移除 (key -> client), 从 client 的 watchedKeys 中移除 [db,?key]? 完? |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/23 20:58:16- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |