? ? ? ? 問題背景:如果某個方法加了Transactional注解,而這個方法中既包括mysql事務又包括redis事務,那么如何做到mysql和redis都回滾?
? ? ? ? mysql事務支持回滾,但redis的事務是不支持回滾的,但它倆都在當前方法的事務里面,所以,無論是mysql操作失敗還是redis操作失敗,都要將mysql和redis中的數據都恢復到之前的狀態,以免發生數據不一致的問題。
? ? ? ? 比如,我們有一個進行db和redis數據更新的方法dataUpdate,這個方法上我們加了Transactional注解,為了保證db和redis數據的最終一致性,我們使用了延遲雙刪策略,所以這個方法的邏輯是:刪redis -> update db -> 刪redis,為了確保不管在這三步中的哪一步執行失敗了,都讓db和redis回滾,我們可以這么做:
? ? ? ? 1、定義刪除redis的方法delInRedis,給此方法聲明拋出異常,讓它在執行失敗時拋出某個類型的異常,比如我們自定義的一個異常類MyRedisOperationException,為dataUpdate方法的Transactional注解設置rollbackFor屬性,讓它指向MyRedisOperationException這類異常;
? ? ? ? 2、update db這一步,如果出現了執行失敗,我們要寫finally語句塊,在finally內部執行redis數據的重新寫入,以回滾第一步對于redis的刪除操作。