西部数码网站流量怎么充,简单的公司网站系统,官方网站的重要性,黑龙江住房和城乡建设局网站转载请注明出处#xff1a;http://www.cnblogs.com/lizo/p/8516502.html 概述 当单库已不能支撑当前业务的时候#xff0c;我们往往都考虑进行分库#xff08;横向拆分或者纵向拆分#xff09;。但分库有个无法回避的问题#xff0c;就是事务问题。网上有很多分布式事务解…转载请注明出处http://www.cnblogs.com/lizo/p/8516502.html 概述 当单库已不能支撑当前业务的时候我们往往都考虑进行分库横向拆分或者纵向拆分。但分库有个无法回避的问题就是事务问题。网上有很多分布式事务解决方案例如XA,TCC等但是最常用也是改造成本最低就是使用最终一致性来保证分布式事务。比较常用的就是使用消息中间件RabbitMqRocketMq通过事务消息来解决最终一致性。参考https://zhuanlan.zhihu.com/p/25933039?utm_sourcetuicoolutm_mediumreferral。 本篇文章将使用数据库的来达到最终一致性的实现方案。 名词解释 主库-拆分前业务访问的数据库分库-拆分后部分业务数据放入到分库中注以下有些内容是在使用事务消息无论是基于数据库还是基于消息队列应该考虑的地方。 基于数据库的事务消息 事务消息 所谓基于数据库的事务消息其实很好理解就是在数据库中创建一个类似消息队列的表用于保存事务消息。在拆分前一个事务中有多个主库的数据操作。如下图 但是在拆分数据库后有业务被拆分到分库中去了这样原有的单库事务被打破但是通过把拆分出去的业务使用一个事务消息来代替事务消息表也是在主库中所以这里还是单库事务后续再通过其他方式去执行该事务消息所对应的业务逻辑即可这样就可以达到最终一致性如下图 事务消息执行器 前面说到了事务消息需要一个处理器来进行执行事务消息所对应的业务逻辑。事务处理器应该是顺序的去读取并执行的。 设想一个场景当出现某一条消息处理失败如果执行器要等当前消息执行成功才继续往后执行甚至该消息永远不会处理成功那么会影响后续消息的执行导致整个系统出现问题。 因此消息处理器即要保证消息处理尽可能处理快又能保证消息最终能执行成功。 在消息执行器中必须设置2个任务 第一个任务,消息处理任务已最快的速度执行消息如果消息处理失败了跳过该消息继续执行后面的消息。第二个任务,消息校验任务这个任务就是顺序检查消息保证所有消息都执行成功如果失败进行重试多次重试失败以后发出告警以让人工介入处理。 如下图 注上图左边那个是消息队列及其处理状态 消息执行的特性 延迟处理性。消息不是实时处理的而是用过消息执行器来异步执行的。因此如果在原有逻辑中需要特别注意后续流程对该消息处理结果是不是有实时依赖性例如后续业务逻辑中会使用该消息处理结果来做一些计算等。处理无序性。由于消息不一定是顺序执行的所有保证即使后生成的消息先执行也不能出现问题。最终成功性。对每条插入的消息保证该条消息一定要能执行成功如何确认消息已执行成功 设想如果分库业务执行成功更新分库然后去更新消息状态主库这样又是一个夸库事务所以得想其他办法来避免最简单的方法就是在分库里面也建一个消息表保存处理的成功的消息。这样通过对比主库和分库的消息表就知道哪些事务消息没有执行成功 消息处理器基本框架 前面介绍了消息处理器的核心功能就 获取消息并把消息发送给业务放处理保证消息执行的成功 为了完成上面功能需要消息处理任务和消息校验任务通过定时调度任务来触发这2个任务例如5s触发一次 消息处理任务 消息处理任务就是通过扫描待处理的消息然后通知业务系统执行。 再次强调消息处理任务不会管消息是否执行成功。都是按照消息队列表顺序执行下去。 消息校验任务 校验任务就是比较主库和分库中的消息记录主库中记录的所有消息分库中记录的执行成功的消息对执行未成功的消息发起重试如果多次重试失败则发出告警需要人工介入。 和基于消息中间件的事务消息比较 相同点 都是采用异步确保最终一致性可以控制异步执行消息的速率可以利用RPC调用的负载均衡消息处理都必须支持重试和幂等性事务消息异步执行失败都没办法回滚产生事务消息的事务 不同点 消息事务的提交 使用消息中间件一般都需要在代码中显示的编写提交中间件事务消息的代码类似下面 public boolean transaction(String text){try {发送事务消息执行本地事务提交事务消息return true;} catch (TmcException e) {return false;}
} 但在实际项目中事务的传播性的问题spring 的事务注解是支持事务的传播性就需要修改业务代码。但使用基于数据库的消息队列就没有这个问题 Transactional
public void publishAS(String text){ 执行本地事务逻辑插入事务消息
} 所以在既有代码改造上特别是复杂系统中使用数据库的事务消息可以减少代码的改动 不需要回调check 我们知道在使用消息中间件的时候都需要实现一个回调接口当事务消息长时间没有commit的时候会调用该接口来确认是否需要commit例如发送消息成功但是在commit的时候网络不可用。而基于数据局的事务消息队列就没有这个问题 更多的数据库访问资源 基于数据库的事务消息也有一个比较明显的缺点 占用更多的数据库空间和数据库访问资源需要额外编写DAO层代码小结 基于数据库和基于消息队列的事务消息的基本思路都一样使用最终一致性来避免分布式事务带来的额外系统复杂性和代码开销。基于数据库的事务消息在既有业务改造中代码变动较小也不需要额外的引入消息中间件但是带来的问题就是对数据库更多的访问。而基于消息中间件的问题就是如何避免在与消息中间件交互的出现问题的时候如何应对。当然以上只是我个人理解如果系统有什么设计不合理或者有改进的地方欢迎讨论。转载于:https://www.cnblogs.com/lizo/p/8516502.html