第 19 章: 事务 ================= 在一个事务开始之后, 服务器判断命令是该入队还是该执行的过程。 .. graphviz:: digraph enque_or_execute { label = "\n图 19-1 服务器判断命令是该入队还是该执行的过程"; node [shape = box]; // command_in [label = "服务器接到来自客户端的命令"]; in_transaction_or_not [label = "这个客户端正处于事务状态?", shape = diamond]; not_exec_and_discard [label = "这个命令是否\nEXEC 、 DISCARD 、\nWATCH 或 MULTI ?", shape = diamond]; enqueu_command [label = "将命令放入事务队列"]; return_enqueued [label = "向客户端返回 QUEUED"]; exec_command [label = "执行这个命令"]; return_command_result [label = "向客户端返回命令的执行结果"]; // command_in -> in_transaction_or_not; in_transaction_or_not -> not_exec_and_discard [label = "是"]; not_exec_and_discard -> enqueu_command [label = "否"]; not_exec_and_discard -> exec_command [label = "是"]; in_transaction_or_not -> exec_command [label = "否"]; exec_command -> return_command_result; enqueu_command -> return_enqueued; } ---- 事务状态。 .. graphviz:: digraph { label = "\n 图 19-2 事务状态"; rankdir = LR; node [shape = record]; //redisClient [label = " redisClient | ... | mstate | ... "]; multiState [label = " multiState | commands | count \n 4 "]; commands [label = " multiCmd[4] | <0> [0] | <1> [1] | <2> [2] | <3> [3] "]; multiCmd0 [label = " multiCmd | argv | argc \n 3 | cmd "]; multiCmd1 [label = " multiCmd | argv | argc \n 2 | cmd "]; multiCmd2 [label = " multiCmd | argv | argc \n 3 | cmd "]; multiCmd3 [label = " multiCmd | argv | argc \n 2 | cmd "]; //redisClient:mstate -> multiState:head; multiState:commands -> commands:head; commands:0 -> multiCmd0:head; commands:1 -> multiCmd1:head; commands:2 -> multiCmd2:head; commands:3 -> multiCmd3:head; argv0 [label = " robj*[3] | { StringObject \n \"SET\" | StringObject \n \"name\" | StringObject \n \"Practical Common Lisp\" } "]; cmd0 [label = " setCommand ", shape = plaintext]; multiCmd0:argv -> argv0; multiCmd0:cmd -> cmd0; argv1 [label = " robj*[2] | { StringObject \n \"GET\" | StringObject \n \"name\" } "]; cmd1 [label = " getCommand ", shape = plaintext]; multiCmd1:argv -> argv1; multiCmd1:cmd -> cmd1; argv2 [label = " robj*[3] | { StringObject \n \"SET\" | StringObject \n \"author\" | StringObject \n \"Peter Seibel\" } "]; cmd2 [label = " setCommand ", shape = plaintext]; multiCmd2:argv -> argv2; multiCmd2:cmd -> cmd2; argv3 [label = " robj*[2] | { StringObject \n \"GET\" | StringObject \n \"author\" } "]; cmd3 [label = " getCommand ", shape = plaintext]; multiCmd3:argv -> argv3; multiCmd3:cmd -> cmd3; } ---- ``watched_keys`` 字典示例。 .. graphviz:: digraph { label = "\n 图 19-5 watched_keys 字典"; rankdir = LR; node [shape = record]; // watched_keys [label = "watched_keys | \"name\" | \"age\" |
\"address\" ", width = 2.0, height = 3.0]; // name_c2 [label = "c2"]; address_c2 [label = "c2"]; name_c10086 [label = "c10086"]; age_c10086 [label = "c10086"]; // watched_keys:name -> c1 -> name_c2 -> name_c10086; watched_keys:age -> c3 -> age_c10086; watched_keys:address -> address_c2 -> c4; } ---- 服务器判断是否执行事务的过程。 .. graphviz:: digraph { label = "\n 图 19-6 服务器判断是否执行事务的过程"; node [shape = box]; exec [label = "客户端向服务器发送 EXEC 命令"]; dirty_cas_or_not [label = "客户端的 \n REDIS_DIRTY_CAS \n 标识是否已经打开?", shape = diamond]; reject [label = "拒绝执行客户端提交的事务"]; ok [label = "执行客户端提交的事务"]; exec -> dirty_cas_or_not; dirty_cas_or_not -> reject [label = "是"]; dirty_cas_or_not -> ok [label = "否"]; }