rabbitMq设置引起的生产问题

  今天,由于凌晨1点开始,数据库出现了问题,这边数据库两个结点,其中一个结点出现了问题。

  然后,由于业务中有一个job,每4分钟查找一个中间表,然后将表中的记录发到queue中去执行。

  queue端处理逻辑是,先执行删除这个中间表,如果没有删除任何记录,则抛出异常。

  如果删除中间表记录成功后,接着处理完这个消息对应的逻辑。


  由于数据库挂了,因此,当queue处理时,去找对应数据库中间表记录,这时会找不到,因此抛出一个异常,最终这个异常被 父类catch住,最终执行rollback。

  但由于数据库原因,这个rollback最终也抛出了异常,这时被spring的ListenerContainer捕捉到。

  重点在于rabbitMq的requeReject之前被设置成true。应该客户端会发送抛出异常的消息给服务器,因此服务器又重新放入了这条message(客户端先发Nack,告诉服务器要删除原有队列中的消息,然后客户端将本地message重新交给服务器,服务器会放入到queue)

 之前讲到的job,之后还是不断查找中间表,然后发往queue。这样queue就不断的累积重复的消息。

 之后,数据库恢复,但由于n个重复的业务消息只会被处理成功一次,其它n-1个都会抛出业务异常,这样服务器不断产生日志,空间被占满。

  最后,将rabbitMq的requeReject设置成false(这时要注意当服务器关掉时,由于spring组件的销毁顺序,先销毁业务组件,然后 MessageListener还是存在,这时就有可能会丢失消息)。

  还有一个,就是在queue的业务处理时,对于已经被删除的中间表记录,只需记个log就可,不需要抛出异常,这需要保证在业务开始前做检查。(删除记录会锁住当前记录,独占),即只要检查通过,就可以处理业务。每个业务消息(相同业务号)只被处理一次,需要由在业务前做删除检查保证。

 总结:

  数据库异常,在访问量大,或者有密集的任务运行时,会产生相当大的日志产生。最好日志文件能够及时的转移到别的机子上。对于数据库异常要相当重视,建立报警机制,服务器的磁盘空间,服务器状态都需要有报警机制。

 业务处理时,对于job轮循中间表处理业务时,也可以对中间表记录加个状态。job取出记录时将其置为待处理。queue消息端,处理成功后,将其置为success,如果碰到数据库异常,这种需要再次处理,这时需要设置requeReject等于true,之后会重新消息这个消息。这种方案,会存在,发送消息给rabbitmq时已经丢了,这时导致中间表对应记录始终处于待处理状态。

  设计编码时,需要考虑全面,对于应用的技术,要相当了解。细节特别重要!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值