本系列故事的全部案例和解决方案只是笔者之前在互联网工做期间的一些事例,仅供你们参考,实际操做应该根据业务和项目状况设计,欢迎你们留言提出宝贵的意见java
小王和小明分别维护分布式系统中A、b两个服务,有一个场景是 A服务会向B服务经过MQ发送事件而且推送用户信息,而后B服务保存用户信息。
spring
有一天,小王和小明由于一件事讨论得热火朝天、各执己见,事情由来以下:数据库
这时候,在一旁扫地的清洁工老梁过来调解,并帮忙排查分析,致使这个问题的主要缘由以下:服务器
伪代码以下:网络
@RabbitHandler public void handle(byte[] message) { try { t = parseBody(messageStr); } catch (Exception e) { log.error("消费消息失败", e.getCause()); } } private void handleMessage(T t) throws MQHandleException { //惟一标识 String key = t.getLockedId(); //获取锁 DistributedLock lock = DistributedLockFactory.getLock(key); try { // 解决分布式服务提交相同资料并发问题 lock.lock(CacheConstants.LOCK_WAIT_TIME, CacheConstants.LOCK_LEASE_TIME, CacheConstants.DEFAULT_CACHE_UNIT); // 处理业务逻辑 handleBusinessLogic(t); } catch (LockException e) { throw new MQHandleException(e); } finally { // 释放锁 lock.unLock(); } }
频繁Redis超时是由于A、B服务共用一个Redis,A服务Key太多把Redis内存资源占满了(也可能链接占满),致使了B服务常常出现链接超时(该故障不是本章主要关注目标)
架构
B服务在已经成功接受到消息后,没有把消息先保存起来,因此也致使了自身并无能力重跑并发
清洁工老梁跟小王和小明进行一番详谈后,了解到他们主要需求有两个:框架
通过上面的分析,老梁的解题思路主要分为两个方向:分布式
通常来讲,常见的微服务架构实现最终一致性有三种模式:可靠事件模式、业务补偿模式、TCC模式。这里AB服务是经过业务补偿模式实现最终一致性,但这里又跟咱们通常的分布式架构的事务问题不一样,这里咱们只须要保证B服务能最终把正常消息事件消费成功便可。微服务
实现思路:
针对于B服务,对于收到的MQ信息没有进行有效的记录,并且MQ信息处理以后,存在修改错误,无法进行对应信息补充修复的功能,增长通用消息处理层,进行消息体的记录和回溯。 在获取消息以后进行一次记录,进行幂等操做和对应的状态更新, 消息状态在业务相关操做完成后,标记为处理完成,认为对应消息状态结束。
这里hash_value是对请求体进行hash计算得出来的一个值,例如:MD五、SHA-2,保证每一个不一样请求的hash码不同,相同的请求hash码相同,能够用于幂等控制。
表大体操做流程:
异常消息有4个状态
待处理
处理中
处理完成
异常
,等待后期人工重跑失败事件队列在这里是采用数据库表代替
由于并不是全部的异常都能重跑就能解决问题,咱们只能针对能够修复的异常进行重试,这里把异常分为两大类:
最后小明负责的B服务按照老梁的思路,从新调整了代码,异常处理流程以下: