宜昌市建設工程質量監(jiān)督站網站百度提交網址
本文基于SpringBoot 2.X
事務在關系型數(shù)據(jù)庫的開發(fā)中經常用到,其實非關系型數(shù)據(jù)庫,比如redis也有對事務的支持,本文主要探討在SpringBoot中如何使用redis事務。
事務的相關介紹可以參考:
0、起因
在一次線上事故中,我們定位到redis的使用存在大value,超過了dubbo的最大數(shù)據(jù)量限制,于是緊急將這個大的對象value拆分成單個的string value。
為了保持數(shù)據(jù)庫和redis雙寫一致,在對數(shù)據(jù)庫進行更新,刪除,插入操作時,要從redis刪除指定的key。
一切都是使用redis的常規(guī)操作,但雷就埋在其中一個數(shù)據(jù)庫的update方法里,這個方法上開啟了事務@Transactional,導致里面的刪除redis key操作也加入了事務。
上線后出現(xiàn)報錯:
這個報錯明確指出,集群模式的redis不支持事務。集群不支持事務的原因可參考此文:Is there any Redis client (Java prefered) which supports transactions on Redis cluster?
1、Spring中的事務
所有數(shù)據(jù)訪問技術都有事務機制,這些技術提供了API來開啟事務、提交事務完成數(shù)據(jù)操作, 或者在發(fā)生錯誤的時候回滾數(shù)據(jù)。
Spring采用統(tǒng)一的機制來處理不同的數(shù)據(jù)訪問技術的事務, Spring的事務提供一個PlatformTransactionManager
的接口,不同的數(shù)據(jù)訪問技術使用不同的接口實現(xiàn)。
數(shù)據(jù)訪問技術 | 實現(xiàn) |
---|---|
JDBC | DataSourceTransactionManager |
JPA | JPATransactionManager |
Hibernate | HibernateTransactionManager |
JDO | JDOTransactionManager |
分布式事務 | JtaTransactionManager |
- 在SpringBoot中開啟事務非常簡單,只需要在方法或類上使用注解@Transactional即可。
- Spring官方文檔中還要求使用@EnableTransactionManagement 開啟事務,但SpringBoot通過自動配置已經幫我們做了,所以SpringBoot中不用寫該注解
@Transactional注解的幾個常用屬性
-
propagation
事務的傳播機制,主要有以下幾種,默認是REQUIRED:
REQUIRED - 方法A調用時候沒有事務新建一個事務,在方法A中調用方法B,將使用相同的事務,如果方法B發(fā)生異常需要回滾,整個事務回滾。
?
REQUIRES_NEW - 方法A調用方法B時,無論是否存在事務都開啟一個新事務,這樣B方法異常不會導致A的數(shù)據(jù)回滾。
?
NESTED - 和REQUIRES_NEW類似,但是只支持JDBC,不支持JPA或Hibernate
SUPPORTS - 方法調用時有事務就用事務,沒事務就不用事務
NOT_SUPPORTED - 強制方法不在事務中執(zhí)行,若有事務,在方法調用到結束階段先掛起事務。
NEVER - 強制不能有事務,若有事務就拋出異常
MANDATORY - 強制必須有事務,如果沒有事務就拋出異常
-
rollbackFor
指定哪些異??梢詫е率聞栈貪L,默認是Throwable的子類
-
noRollbackFor
執(zhí)行哪些異常不可用引起事務回滾,默認是Throwable的子類
2、@Transactional事務失效的情況
- 只對public方法生效。默認的protected和private方法上寫上@Transactional不會報錯,但該方法上的事務不生效,官方原文:Method visibility and @Transactional;
- 默認情況(只寫@Transactional不填寫rollbackFor參數(shù))下此注解會對unchecked異常進行回滾,對checked異常不回滾;
- 類內部未開啟事務的方法調用開啟事務的方法
針對3,引用丁雪豐的《Spring全家桶》視頻中的解釋:
Spring的聲明式事務本質上是通過AOP來增強了類的功能
Spring的AOP本質上就是為類做了一個代理看似在調用自己寫的類,實際用的是增強后的代理類
下圖描述了方法被事務代理時的流程,來源:Spring AOP
?
3、SpringBoot整合Redis事務實踐
下面我們搭建一個最簡單的SpringBoot整合redis的工程用代碼來驗證redis事務
-
SpringBoot整合Redis
SpringBoot整合redis使用的是
spring-boot-starter-data-redis
,redis事務依賴于jdbc的事務管理,所以還需要引入jdbc
pom相關引入:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency><groupId>com.h2database</groupId><artifactId>h2</artifactId><scope>runtime</scope>
</dependency>
-
開啟Redis事務
編寫redis配置類,開啟redis事務,配置事務管理
@Configuration
public class RedisConfig {@Beanpublic StringRedisTemplate StringRedisTemplate(RedisConnectionFactory factory) {StringRedisTemplate template = new StringRedisTemplate(factory);/*** description 開啟redis事務(僅支持單機,不支持cluster)**/template.setEnableTransactionSupport(true);return template;}/*** description 配置事務管理器**/@Beanpublic PlatformTransactionManager transactionManager(DataSource dataSource){return new DataSourceTransactionManager(dataSource);}
}
-
代碼驗證
針對本文討論,設計了四個驗證方法,可自行驗證
/*** description 不帶事務set* return java.lang.String* author 鄭曉龍* createTime 2019/12/12 16:36**/
@GetMapping("put")
public void put(String key, String value) {redisService.put(key, value);
}
/*** description 帶事務set* return java.lang.String* author 鄭曉龍* createTime 2019/12/12 16:36**/
@GetMapping("putWithTx")
public void putWithTx(String key, String value) {redisService.putWithTx(key, value);
}
/*** description 調用帶事務方法不生效的情況* return java.lang.String* author 鄭曉龍* createTime 2019/12/12 16:36**/
@GetMapping("invokeWithPutTx")
public void invokeWithPutTx(String key, String value) {redisService.invokePutWithTx(key, value);
}
/*** description 調用帶事務方法生效的情況* return java.lang.String* author 鄭曉龍* createTime 2019/12/12 16:36**/
@GetMapping("invokeWithPutTx2")
public void invokeWithPutTx2(String key, String value) {redisService.invokePutWithTx2(key, value);
}
4、總結:
- redis事務只支持單機,不支持cluster
- 需要開啟事務時,只需要在對應的方法或類上使用@Transactional注解即可,SpringBoot自動開啟了@EnableTransactionManagement
- 需要注意事務不生效的幾種情況
- redis事務依賴于jdbc的事務管理
5、示例代碼及參考:
示例代碼: redis-transaction
- Transaction Management
- Transaction Propagation
- Transactional Support
- 《Spring全家桶》丁雪豐