1. 程式人生 > 其它 >Redis,資料庫,MQ,檔案服務等 多個資源的業務操作事務一致性思路

Redis,資料庫,MQ,檔案服務等 多個資源的業務操作事務一致性思路

public interface Service{

  //業務方法
  doBusiness();

  //資料庫更新方法
  doBusinessTX();

}

@Service
public class ServiceImpl implements Service,ApplicationContextAware{

  //自己注入自己
  @Autowired
  private Service ServiceProxy;

  //或者使用Aware介面獲取BeanFactory獲取當前物件事務代理物件
  @Override
  public void setApplicationContext(ApplicationContext ctx) throws BeansException{
    this.Service = ctx.getBean(Service.class);
  }

  @Transactional(rollback=RuntimeException.class)//預設RuntimeException和虛擬機器Error回滾
  public void doBusinessTX(){
    資料庫更新 可丟擲RuntimeException 自動觸發資料庫回滾
    return;
  }


  public void operateRedis(){
    //redisTemplate.eval 涉及多個KEY操作使用LUA指令碼
  }

  public void operateRedisRollback(){
    //redisTemplate.eval 執行LUA指令碼 多個KEY同時操作 原子執行 回退redis修改
  }

  public void operateMQ() throws MQException{
    //傳送MQ 捕捉RuntimeException 轉換為MQException再丟擲 其他異常轉換為MQException
  }

  @Override
  public void doBusiness(){
    try{
      this.operateRedis();//先操作redis
      this.ServiceProxy.doBusinessTX();//再操作資料庫,代理物件呼叫事務方法 方法結束事務提交
      this.operateMQ();//最後傳送MQ 傳送失敗需重發 重發仍失敗丟擲MQException
    }catch(RuntimeException e){
      //執行時異常 事務方法丟擲後 資料庫已回滾 需手動回滾redis
      this.operateRedisRollback();
    }catch(MQException me){
      //MQException 後發MQ,如果時先發MQ,則可能涉及資料庫事務失敗再發送撤銷MQ,可能觸發MQ關聯絡統回滾,增加複雜性,如先發MQ最後確認,則資料庫事務期間佔用MQ連結而不確認,實際效果同後發MQ,如後發MQ重試仍傳送失敗,通常業務狀態置為異常,需手動衝正或非同步定時任務處理或延遲傳送,如果還有檔案伺服器的操作,一般不能將耗時IO操作放在資料庫事務中,可非同步調起檔案服務操作,並可使用類似訊號量限制IO。
    }finally{

    }
  }
}