|
| 1 | +[English](./README.md) | 简体中文 |
| 2 | + |
| 3 | +# dtmcli-csharp |
| 4 | + |
| 5 | +`dtmcli-csharp` 是分布式事务管理器 DTM 的 C# 客户端,使用 HTTP 协议和 DTM 服务端进行交互。 |
| 6 | + |
| 7 | +目前已经支持 SAGA 、 TCC 和二阶段消息三种事务模式。 |
| 8 | + |
| 9 | + |
| 10 | +## dtm分布式事务管理服务 |
| 11 | + |
| 12 | +DTM是一款变革性的分布式事务框架,提供了傻瓜式的使用方式,极大的降低了分布式事务的使用门槛,改变了“能不用分布式事务就不用”的行业现状。 dtm 的应用范围非常广,可以应用于以下常见的领域: |
| 13 | +- [非单体的订单系统,大幅简化架构](https://dtm.pub/app/order.html) |
| 14 | +- [秒杀系统,做到在Redis中精准扣库存](https://dtm.pub/app/flash.html) |
| 15 | +- [保证缓存与DB的一致性](https://dtm.pub/app/cache.html) |
| 16 | +- 微服务架构中跨服务更新数据保证一致性 |
| 17 | + |
| 18 | +他优雅的解决了幂等、空补偿、悬挂等分布式事务难题,提供跨语言,跨存储引擎组合事务的强大功能: |
| 19 | + |
| 20 | +<img src="https://pica.zhimg.com/80/v2-2f66cb3074e68d38c29694318680acac_1440w.png" height=250 /> |
| 21 | + |
| 22 | +## 亮点 |
| 23 | + |
| 24 | +* 极易接入 |
| 25 | + - 支持HTTP,提供非常简单的接口,极大降低上手分布式事务的难度,新手也能快速接入 |
| 26 | +* 使用简单 |
| 27 | + - 开发者不再担心悬挂、空补偿、幂等各类问题,框架层代为处理 |
| 28 | +* 跨语言 |
| 29 | + - 可适合多语言栈的公司使用。方便go、python、php、nodejs、ruby、c# 各类语言使用。 |
| 30 | +* 易部署、易扩展 |
| 31 | + - 仅依赖mysql,部署简单,易集群化,易水平扩展 |
| 32 | +* 多种分布式事务协议支持 |
| 33 | + - TCC、SAGA、XA、事务消息 |
| 34 | + |
| 35 | +## 与其他框架对比 |
| 36 | + |
| 37 | +目前开源的分布式事务框架,暂未看到非Java语言有成熟的框架。而Java语言的较多,有阿里的SEATA、华为的ServiceComb-Pack,京东的shardingsphere,以及himly,tcc-transaction,ByteTCC等等,其中以seata应用最为广泛。 |
| 38 | + |
| 39 | +下面是dtm和seata的主要特性对比: |
| 40 | + |
| 41 | +| 特性| DTM | SEATA |备注| |
| 42 | +|:-----:|:----:|:----:|:----:| |
| 43 | +| 支持语言 |<span style="color:green">Golang, C#, Java, Python, PHP及其他</span>|<span style="color:orange">Java</span>|dtm可轻松接入一门新语言| |
| 44 | +|异常处理| <span style="color:green">[子事务屏障自动处理](https://zhuanlan.zhihu.com/p/388444465)</span>|<span style="color:orange">手动处理</span> |dtm解决了幂等、悬挂、空补偿| |
| 45 | +| TCC事务| <span style="color:green">✓</span>|<span style="color:green">✓</span>|| |
| 46 | +| XA事务|<span style="color:green">✓</span>|<span style="color:green">✓</span>|| |
| 47 | +|AT事务|<span style="color:red">✗</span>|<span style="color:green">✓</span>|AT与XA类似,性能更好,但有脏回滚| |
| 48 | +| SAGA事务 |<span style="color:orange">简单模式</span> |<span style="color:green">状态机复杂模式</span> |dtm的状态机模式在规划中| |
| 49 | +|事务消息|<span style="color:green">✓</span>|<span style="color:red">✗</span>|dtm提供类似rocketmq的事务消息| |
| 50 | +|通信协议|HTTP|dubbo等协议,无HTTP|dtm后续将支持grpc类协议| |
| 51 | +|star数量|<img src="https://img.shields.io/github/stars/yedf/dtm.svg?style=social" alt="github stars"/>|<img src="https://img.shields.io/github/stars/seata/seata.svg?style=social" alt="github stars"/>|dtm从20210604发布0.1,发展快| |
| 52 | + |
| 53 | +从上面对比的特性来看,如果您的语言栈包含了Java之外的语言,那么dtm是您的首选。如果您的语言栈是Java,您也可以选择接入dtm,使用子事务屏障技术,简化您的业务编写。 |
| 54 | + |
| 55 | + |
| 56 | +## 安装 |
| 57 | + |
| 58 | +通过下面的命令安装 nuget 包 |
| 59 | + |
| 60 | +```sh |
| 61 | +dotnet add package Dtmcli |
| 62 | +``` |
| 63 | + |
| 64 | +## 配置 |
| 65 | + |
| 66 | +这里有两种方式进行配置 |
| 67 | + |
| 68 | +1. 使用 setup action |
| 69 | + |
| 70 | +```cs |
| 71 | +services.AddDtmcli(x => |
| 72 | +{ |
| 73 | + // DTM server 的 HTTP 地址 |
| 74 | + x.DtmUrl = "http://localhost:36789"; |
| 75 | + |
| 76 | + // 请求 DTM server 的超时时间, 单位是毫秒 |
| 77 | + x.DtmTimeout = 10000; |
| 78 | + |
| 79 | + // 请求分支事务的超时时间, 单位是毫秒 |
| 80 | + x.BranchTimeout = 10000; |
| 81 | + |
| 82 | + // 子事务屏障的数据库类型, mysql, postgres, sqlserver |
| 83 | + x.DBType = "mysql"; |
| 84 | + |
| 85 | + // 子事务屏障的数据表名 |
| 86 | + x.BarrierTableName = "dtm_barrier.barrier"; |
| 87 | +}); |
| 88 | +``` |
| 89 | + |
| 90 | +2. 使用 `IConfiguration` |
| 91 | + |
| 92 | +```cs |
| 93 | +services.AddDtmcli(Configuration, "dtm"); |
| 94 | +``` |
| 95 | + |
| 96 | +添加配置文件,以 JSON 为例: |
| 97 | + |
| 98 | +```JSON |
| 99 | +{ |
| 100 | + "dtm": { |
| 101 | + "DtmUrl": "http://localhost:36789", |
| 102 | + "DtmTimeout": 10000, |
| 103 | + "BranchTimeout": 10000, |
| 104 | + "DBType": "mysql", |
| 105 | + "BarrierTableName": "dtm_barrier.barrier", |
| 106 | + } |
| 107 | +} |
| 108 | +``` |
| 109 | + |
| 110 | +## 用法 |
| 111 | + |
| 112 | +### SAGA |
| 113 | + |
| 114 | +```cs |
| 115 | +public class MyBusi |
| 116 | +{ |
| 117 | + private readonly Dtmcli.IDtmTransFactory _transFactory; |
| 118 | + |
| 119 | + public MyBusi(Dtmcli.IDtmTransFactory transFactory) |
| 120 | + { |
| 121 | + this._transFactory = transFactory; |
| 122 | + } |
| 123 | + |
| 124 | + public async Task DoBusAsync() |
| 125 | + { |
| 126 | + var gid = Guid.NewGuid().ToString(); |
| 127 | + var req = new BusiReq { Amount = 30 }; |
| 128 | + |
| 129 | + // NOTE: After DTM v1.12.2 |
| 130 | + // when svc start with http or https, DTM server will send HTTP request to svc |
| 131 | + // when svc don't start with http or https, DTM server will send gRPC request to svc |
| 132 | + var svc = "http://localhost:5005"; |
| 133 | + |
| 134 | + var saga = _transFactory.NewSaga(gid); |
| 135 | + // 添加子事务操作 |
| 136 | + saga.Add( |
| 137 | + // 正向操作 URL |
| 138 | + svc + "/api/TransOut", |
| 139 | + |
| 140 | + // 逆向操作 URL |
| 141 | + svc + "/api/TransOutCompensate", |
| 142 | + |
| 143 | + // 参数 |
| 144 | + req); |
| 145 | + saga.Add( |
| 146 | + svc + "/api/TransIn", |
| 147 | + svc + "/api/TransInCompensate", |
| 148 | + req); |
| 149 | + |
| 150 | + await saga.Submit(); |
| 151 | + } |
| 152 | +} |
| 153 | +``` |
| 154 | + |
| 155 | +### TCC pattern |
| 156 | + |
| 157 | +```cs |
| 158 | +public class MyBusi |
| 159 | +{ |
| 160 | + private readonly Dtmcli.TccGlobalTransaction _globalTransaction; |
| 161 | + |
| 162 | + public MyBusi(Dtmcli.TccGlobalTransaction globalTransaction) |
| 163 | + { |
| 164 | + this._globalTransaction = globalTransaction; |
| 165 | + } |
| 166 | + |
| 167 | + public async Task DoBusAsync() |
| 168 | + { |
| 169 | + var gid = Guid.NewGuid().ToString(); |
| 170 | + var req = new BusiReq { Amount = 30 }; |
| 171 | + var svc = "http://localhost:5005"; |
| 172 | + |
| 173 | + await _globalTransaction.Excecute(gid, async tcc => |
| 174 | + { |
| 175 | + // 调用 TCC 子事务 |
| 176 | + await tcc.CallBranch( |
| 177 | + // 参数 |
| 178 | + req, |
| 179 | + |
| 180 | + // Try 阶段的 URL |
| 181 | + svc + "/api/TransOutTry", |
| 182 | + |
| 183 | + // Confirm 阶段的 URL |
| 184 | + svc + "/api/TransOutConfirm", |
| 185 | + |
| 186 | + // Cancel 阶段的 URL |
| 187 | + svc + "/api/TransOutCancel"); |
| 188 | + |
| 189 | + await tcc.CallBranch( |
| 190 | + req, |
| 191 | + svc + "/api/TransInTry", |
| 192 | + svc + "/api/TransInConfirm", |
| 193 | + svc + "/api/TransInCancel"); |
| 194 | + }); |
| 195 | + } |
| 196 | +} |
| 197 | +``` |
| 198 | + |
| 199 | +### 二阶段消息 |
| 200 | + |
| 201 | +```cs |
| 202 | +public class MyBusi |
| 203 | +{ |
| 204 | + private readonly Dtmcli.IDtmTransFactory _transFactory; |
| 205 | + |
| 206 | + public MyBusi(Dtmcli.IDtmTransFactory transFactory) |
| 207 | + { |
| 208 | + this._transFactory = transFactory; |
| 209 | + } |
| 210 | + |
| 211 | + public async Task DoBusAsync() |
| 212 | + { |
| 213 | + var gid = Guid.NewGuid().ToString(); |
| 214 | + var req = new BusiReq { Amount = 30 }; |
| 215 | + var svc = "http://localhost:5005"; |
| 216 | + |
| 217 | + var msg = _transFactory.NewMsg(gid); |
| 218 | + // 添加子事务操作 |
| 219 | + msg.Add( |
| 220 | + // 操作的 URL |
| 221 | + svc + "/api/TransOut", |
| 222 | + |
| 223 | + // 参数 |
| 224 | + req); |
| 225 | + msg.Add( |
| 226 | + svc + "/api/TransIn", |
| 227 | + req); |
| 228 | + |
| 229 | + // 用法 1: |
| 230 | + // 发送 prepare 消息 |
| 231 | + await msg.Prepare(svc + "/api/QueryPrepared"); |
| 232 | + // 发送 submit 消息 |
| 233 | + await msg.Submit(); |
| 234 | + |
| 235 | + // 用法 2: |
| 236 | + using (var conn = GetDbConnection()) |
| 237 | + { |
| 238 | + await msg.DoAndSubmitDB(svc + "/api/QueryPrepared", conn, async tx => |
| 239 | + { |
| 240 | + await conn.ExecuteAsync("insert ....", new { }, tx); |
| 241 | + await conn.ExecuteAsync("update ....", new { }, tx); |
| 242 | + await conn.ExecuteAsync("delete ....", new { }, tx); |
| 243 | + }); |
| 244 | + } |
| 245 | + } |
| 246 | +} |
| 247 | +``` |
| 248 | + |
| 249 | + |
| 250 | +## 可运行的使用示例 |
| 251 | + |
| 252 | +见[https://github.com/dtm-labs/dtmcli-csharp-sample](https://github.com/dtm-labs/dtmcli-csharp-sample) |
| 253 | + |
| 254 | +## 联系我们 |
| 255 | +### 公众号 |
| 256 | +dtm官方公众号:分布式事务,大量干货分享,以及dtm的最新消息 |
| 257 | +### 交流群 |
| 258 | +请加 yedf2008 好友或者扫码加好友,验证回复 csharp 按照指引进群 |
| 259 | + |
| 260 | + |
| 261 | + |
0 commit comments