
公司缓存问题和解决办法
公司缓存设计:
第一次产生问题:
解决方案:
scheduleAtFixedRate()在做定时任务的时候 是以上一个任务开始的时间计时,120秒过去后,检测上一个任务是否执行完毕,如果上一个任务执行完毕,则当前任务立即执行,如果上一个任务没有执行完毕,则需要等上一个任务执行完毕后立即执行。关于定时线程池,好多人认为设置好频率(比如1Min),它会按照这个间隔按部就班的工作。但是,如果其中一次调度任务卡住的话,不仅这次调度失败,而且整个线程池也会停在这次调度上。所以认为scheduleAtFixedRate()做定时任务,不太稳定,同时当线程池耗尽后,对定时任务也有影响 故换成了@Scheduled做定时任务管理,观察一段时间后,问题暂时解决
第二次产生问题:
解决方案:
业务变成的service中有事务,而mq产生的消息是在事务未提交之前发送,门户端接受后就刷新,数据库数据其实还是历史数据. 把mq产生的消息放到了变更的事务之外,同时门户在收到消息后加了20秒的等待时间,到期后刷新缓存
第三次问题:
解决方案:
第二次将缓存提出来放到了事务之外,但是当某一次事务提交后,产线消息,在消费消息刷新缓存时,有一个更新操作,更新操作和之前的事务操作的是同一张表,造成表锁,等待时长过长,造成报错
具体的业务场景:
某一种杂志的网络版整期发布,一个整期中包含多个文章,整期发布除了变更整期的状态,还行处理整期下的文章状态,同时门户的缓存主要针对的是文章,即整期发布后刷新门户的文章缓存整期发布时一个比较大的事务,其中会更新文章相关表的一个状态字段,但是在整期中又循环发送mq消息,去刷新门户的缓存,当门户的缓存刷新的时候,还有同步的一个init文章相关内容的操作,会更新之前事务操作的表,造成事务未提交等待着,而产生的多条消息 同时进行了阻塞 造成了等待超时.
解决办法:
采用afterCommet方法, @TransactionalEventListener 监听器,把之前的产生消息的地方换成了事件,当事务提交后,触发监听器事件,产生mq消息把init方法放到其他地方,只刷新缓存,和redis交互,只查 不修改表中的值
下一步考虑使用Canal监听数据库数据变化