一个Mysql事务隔离级别和一个MQ异步转同步问题

Mysql事务隔离级别问题

和朋友聊天提到一个mysql事务隔离级别相关的问题。朋友说他们现在采用默认的隔离级别可重复读,觉得效率太低了,问怎么改进。

我就说了一个线上故障的事例。原因是当时程序代码中在事务中包裹了一个给MQ发消息的步骤。当时用的RabbitMQ,同步写。消息队列积压了,写入没有成功直到超时。事务执行时间过长,导致数据库连接池被打满了,拖垮了整个系统。所以我们以后都要求事务中不能包含外部调用。我的逻辑是既然已经使用事务了,四种隔离级别:读未提交、读已提交、可重复读和串行化。读已提交和可重复读都是通过MVCC来实现的,不是靠加锁。既然使用了事务,基本的效率开销就不太好避免。更可行的方法是缩小事务粒度,所以就说了刚才的事例。已经有了业务量的话,要考虑风险。

但如果这个是新开发一个代码,如果是我的话,我可能会尽量避免使用事务,改用乐观锁或者分布式事务的思想来解决问题。这里说的是分布式事务的思想,不是真正的分布式事务,不需要跨系统。举个例子:如果订单是用子母表来实现的。比如一个是基本表,一个是详情表,都是订单号作为主键。要进行插入操作,需要同时成功或者同时失败。这时候可以采用TCC补偿事务来实现。两个插入都执行,如果一个成功,一个失败,就尝试失败重试,重试失败确实产生了脏写,就把插入成功的那条状态改为无效,考虑这个概率非常低,这个代价是可是承受的。这种方式好处一方面是99%以上的情况避免了事务和加锁的开销,当然插入操作数据库执行时都是加锁的,这个不考虑。另一方面,将来咱们业务量更大了,需要对数据库表做垂直拆分,将表拆到两个数据库里也没有那么难,但是用事务强绑定了拆分成本就高出太多了。

MQ异步转同步问题

朋友也提到说这边说使用了MQ,但是想要达到同步的一个效果,要怎么做。我当时就问因为MQ本身就是做异步的,咱们这边想要的效果是不是减少延迟。朋友说是。如果是我的话,如果根本问题是延迟大,那第一步我会先根据用户行为统计等指标决定一个延迟可接受范围。第二步我会将咱们的系统分段,统计各段的延迟,看看性能瓶颈究竟在哪里。如果大头在网络,可能内部的优化是杯水车薪,可能需要靠增加带宽或者升级网卡等手段解决。

如果是内部优化可以解决的,比如MQ上的延迟,如果MQ使用的是kafka的话,kafka生产端是需要超过一定时间或者达到一定数量才写入broker的,那是不是可以适当把时间调小,批量的数量调小来达到减小延迟的目的。Broker端是不是可以通过增加partition来增加并行度减小延迟。消费端不采用pull的方式消费消息,而是采用push的方式减少延迟。这个调整的过程也需要非常谨慎。曾经有个小伙调整了一个MQ的参数,MQ用的是beanstalked。有个reserved的参数,是调整消费端阻塞等待消息的时长的。原本时间是等待5s没有消息就返回。他调整成了0s,代表线程如果检测到没有消息就不等待直接做别的事情了。他可能认为这是把阻塞改成非阻塞,效率是提高的。所以没有测试,也没有跟任何人讲,也没做压测,直接自己偷偷上线了。结果上线后在一个高峰期性能扛不住了,回滚代码后解决。

可能一般的思路是梳理逻辑,进行逻辑优化。如果是普通的优化,特别是对于IO密集型的业务,可能效果不是很明显。咱们的代码运行,只算内存和数据库交互,一般情况下最多也就是几十ms的时间。在这个基础上的优化提高可能不是很大,风险却很大。但是如果能够通过梳理逻辑,将逻辑拆分,做成两阶段或者三阶段提交的话,效果可能是很明显的。举个例子,我做容器化平台时,创建容器的过程就类似于分布式事务里的三阶段提交。第一阶段是校验用户提交的参数并确认创建容器的资源充足,这是确认阶段。准备阶段将先将资源预占住,将创建容器的信息插入到数据库中并发送MQ异步的去处理真正用k8s来创建容器的过程。在准备完成就会给用户反馈请求已经受理,这个过程非常快,用户不用等待容器创建完再得到响应。最后用通知的方式返回真正的创建容器结果。

这种拆分在金融领域也经常用。比如退款,首先校验符合退款条件,将退款信息插入数据库,给用户返回退款已受理,资金会在多少时间内到账,真正资金到账的过程是很慢的。

但是对于业务已经有一定规模的,一旦涉及到这种逻辑调整,都需要谨慎再谨慎。根据海勒姆法则,当一个 API 有足够多的用户,在契约中承诺了什么并不重要:系统中所有看得见的行为都会有某个人依赖。所以可能自认为过程中修正的一些逻辑,反而造成影响。比如有些负负得正的情况。所以这种大的逻辑调整,我一般会采用长期灰度切换,同时采用开关上线的方式做紧急预案。

这种逻辑改造一般建议用在新业务上,本来该复用老逻辑的,用一个防腐层把新业务引到新逻辑上,为后续业务扩展做好基础。逻辑优化的事情有时候可能用一些更简单的方法能达到一个更好的效果。举个例子:两个公司对接,使用的是MQ,双方都有作为生产端和消费端的业务。A方工作日下午5点开始会批量下发对账文件,文件很大,是被切割成几M大小的文件下发下来的。有个周一下午5点半左右的时候,B方给A方发消息就超时了,超时时间是5s。查了日志,我们收到上游的请求后程序处理用了几毫秒就发给了MQ,但是查了MQ的日志,3秒多之后MQ才收到。这段时间内存飙升到了90%多。Buffer/cache却比平时减少了200M,理论上有大量文件传输应该增加才对。TOP命令发现wa的值显示IO等待时间很长。查了网卡流量,平时大概是0.5M,出现问题的时间点是20MTPS。虽然升高了很多倍,但是对于千兆网卡来说也不算什么。问题还在于内存不足,导致buffer/cache减少影响了IO性能,统计调整后的下午5点到7点平均耗时比原来减少了23ms

  • 19
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值