分布式事务框架Hmily的使用问题总结

1. Hmily的性能问题?

答:Hmily是采用AOP切面的方式与你的RPC方法绑定,无非就是在你RPC调用的时候,保存了日志(通过异步disruptor),传递了一些参数。现在confrim,cancel也都为异步的调用,因此其性能与你的rpc性能一样。记住Hmily不生产事务,Hmily只是分布式事务的搬运工。之前Hmily在AOP切面加了一把锁,导致了性能下降。现在已经全部修复,并且全部异步化。

2. 关于RPC调用超时Hmily是怎么处理的?

答: 我们支持在分布式环境中调用一个RPC方法,如果超时了。比如dubbo设置的超时时间是100ms,可能你的方法用了140ms,但是你的方法是执行成功了的。但是对调用方来说,你是失败的。这个时候需要回滚。所以Hmily的做法是。调用者认为你是失败的,不会将加入的回滚调用链条中。因此超时的rpc接口方,进行自身的回滚。会有一个定时任务来进行回滚,因为日志状态是try阶段,会调用cancel方法进行回滚,从而到达最终一致性!

3. Hmily支持集群部署的问题?以及集群环境中,定时任务日志恢复的问题?

答:Hmily是和你的应用AOP切面绑定在一起的,天然支持集群。集群环境中定时恢复问题,其实几乎没有,除非你的集群同时一下挂掉,才会有这个问题。当你集群同时挂掉,在恢复的时候,日志会有一个version字段,更新成功的,才会去进行恢复。

4. Hmily是异步保存日志的,那么很极端情况下(代码刚好执行到这一行,然后jvm退出,断电啦什么的),日志还没保存那怎么处理呢?

答:在AOP切面中,会先进行日志的异步保存,注意状态是PRE_TRY。在try执行完成后,更新为try。就算存在断电,什么你在打断电调试,然后kill服务之类的。(Mysql我都可以让他事务失效,你信不信?)我只能说,不要花大力气去解决那些偶然的事情,最好的解决办法是不解决它。

5.Hmily针对高并发时候的参数配置调优。

可能这部门内容针对熟悉Hmily的人来说,不熟悉的也没关系。直接上github上看相关文档就好。

  • hmily支持Spring bean xml 方式的配置,同时也支持spring boot start yml方式的配置。

serializer :这里我推荐使用是kroy。当然hmily也支持hessian,protostuff,jdk。在我们测试中表现为: ​ kroy>hessian>protostuff>jdk

recoverDelayTime :定时任务延迟时间(单位是秒,默认120。这个参数只是要大于你的rpc调用的超时时间设置。

retryMax : 最大重复次数,默认3次。当你的服务down机,定时任务会执行retryMax次数去执行你的cancel还是confrim。

bufferSize: disruptor的bufferSize,当高并发的时候,可以调大。注意是 2n

consumerThreads distuptor消费线程数量,高并发的时候,可以调大。

started: 注意在是发起方的时候,把此属性设置为true。参与方为false。

asyncThreads 异步执行confirm和cancel线程池线程的大小,高并发的时候请调大

接下来是最重要的事务日志的存储 在我们的压测中,推荐使用mongo。表现为 mongodb>redis集群>mysql>zookeeper

6.如果你采用mongodb存储日志,配置如下(url可以配置成mongdb集群的url)

7.如果你采用redis存储日志,配置如下:

  • redis单节点
  • redis哨兵模式集群:
  • redis集群:

8.如果你采用zookeeper存储日志,配置如下:

小结

使用Hmily,一个注解,几行配置轻轻松松搞定高并发分布式事务!

0

关于 MyCat 分库分表的一些理解

MyCat 是基于服务器代理模式的数据库分库的中间件,原理是对 SQL 进行转发,具体的架构图如下:

我们知道,数据的拆分必然会对事物的原子性带来影响,那如果保证在分库的同时,又能保证事务的原子性呢?

如何解决分布式事务

XA 协议

XA协议是一个开源的事务协议。

XA 协议在第二段协议 commit 事提交务后,如果出现了有的机器事务没有提交成功,有的机器已经提交成功,这时已经提交的数据,数据就无法再次回滚,这样就造成了数据不一致的问题。

三段提交协议

具体的协议如下:

相对于 XA 多了一个 Precommit的过程,在 Do-Commit的时候也增加了超时操作,避免了 XA 在 commit 无法收到 Ack 时候,出现了阻塞的现象。

业务的规则避免

这个是一个讨巧的方案,具体的做法是所有的业务表的修改和删除等操作,最终都能路由到一个 MySQL 的节点上面,这样就不存在分布式的事务问题。

如何解决唯一主键(自增)

这个本事是分布式的归一的一个思想。具体实施的思路有下面四种方式:

  1. 本地文件方式
  2. 数据库方式
  3. 时间戳
  4. 分布式zookeeper生成ID

如何查询非分片规则的数据

这个问题是一个很纠结的问题,因为没有什么特别好的办法。具体的思路应该有两种:

  1. 轮询各个节点查询,但是会带来性能的浪费。
  2. 未分片的字段与分片字段做一个映射,现根据非分片字段查询出分片字段。例如: 我们根据 Id 进行分片,如果我们想根据 userId 查询数据,有什么办法?首先要保证在业务数据的数量级,userid 一定是小于 id 的量级,所以我们可以直接存储 userid-> id1,id2….idn ,然后根据id 的集合查询出对应的数据。
+2