激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語(yǔ)言|JavaScript|易語(yǔ)言|vb.net|

服務(wù)器之家 - 編程語(yǔ)言 - Java教程 - Spring Boot2+JPA之悲觀鎖和樂(lè)觀鎖實(shí)戰(zhàn)教程

Spring Boot2+JPA之悲觀鎖和樂(lè)觀鎖實(shí)戰(zhàn)教程

2022-02-20 12:08Moshow鄭鍇 Java教程

這篇文章主要介紹了Spring Boot2+JPA之悲觀鎖和樂(lè)觀鎖實(shí)戰(zhàn)教程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

前言

大量的請(qǐng)求,或者同時(shí)的操作,容易導(dǎo)致系統(tǒng)在業(yè)務(wù)上發(fā)生并發(fā)的問(wèn)題. 通常講到并發(fā),解決方案無(wú)非就是前端限制重復(fù)提交,后臺(tái)進(jìn)行悲觀鎖或者樂(lè)觀鎖限制.

悲觀鎖與并發(fā)

悲觀鎖(Pessimistic Lock),顧名思義,就是很悲觀,每次去拿數(shù)據(jù)的時(shí)候都認(rèn)為別人會(huì)修改,所以每次在拿數(shù)據(jù)的時(shí)候都會(huì)上鎖,這樣別人想拿這個(gè)數(shù)據(jù)就會(huì)block直到解鎖,可以理解為獨(dú)占鎖。在java中synchronized和ReentrantLock重入鎖等鎖就是悲觀鎖,數(shù)據(jù)庫(kù)中表鎖、行鎖、讀寫鎖等也是悲觀鎖。

利用SQL的for update解決并發(fā)問(wèn)題

行鎖就是操作數(shù)據(jù)的時(shí)候把這一行數(shù)據(jù)鎖住,其他線程想要讀寫必須等待,但同一個(gè)表的其他數(shù)據(jù)還是能被其他線程操作的。只要在需要查詢的sql后面加上for update,就能鎖住查詢的行,特別要注意查詢條件必須要是索引列,如果不是索引就會(huì)變成表鎖,把整個(gè)表都鎖住。

?
1
2
3
4
public interface ArticleRepository extends JpaRepository<Article, Long> {
    @Query(value = "select * from article a where a.id = :id for update", nativeQuery = true)
    Optional<Article> findArticleForUpdate(Long id);
}

利用JPA的@Lock行鎖注解解決并發(fā)問(wèn)題

如果說(shuō)for update的做法太原始,那么JPA有提供一個(gè)更加優(yōu)雅的方法,就是@Lock注解 .

為Repository添加JPA的鎖方法,其中LockModeType.PESSIMISTIC_WRITE參數(shù)就是行鎖。

關(guān)于LockModeType這個(gè)類型,可以在這找到文檔 https://docs.oracle.com/javaee/7/api/javax/persistence/LockModeType.html

  • NONE: No lock.
  • OPTIMISTIC: Optimistic lock.
  • OPTIMISTIC_FORCE_INCREMENT: Optimistic lock, with version update.
  • PESSIMISTIC_FORCE_INCREMENT: Pessimistic write lock, with version update.
  • PESSIMISTIC_READ: Pessimistic read lock.
  • PESSIMISTIC_WRITE: Pessimistic write lock.
  • READ: Synonymous with OPTIMISTIC.
  • WRITE: Synonymous with OPTIMISTIC_FORCE_INCREMENT.
?
1
2
3
4
5
public interface ArticleRepository extends JpaRepository<Article, Long> {
    @Lock(value = LockModeType.PESSIMISTIC_WRITE)
    @Query("select a from Article a where a.id = :id")
    Optional<Article> findArticleWithPessimisticLock(Long id);
}

如果是@NameQuery,則可以

?
1
2
@NamedQuery(name="lockArticle",query="select a from Article a where a.id = :id",lockMode = PESSIMISTIC_READ)
public class Article

如果用entityManager的方式,則可以設(shè)置LocakMode:

?
1
2
3
4
Query query = entityManager.createQuery("from Article where articleId = :id");
query.setParameter("id", id);
query.setLockMode(LockModeType.PESSIMISTIC_WRITE);
query.getResultList();

樂(lè)觀鎖與并發(fā)

樂(lè)觀鎖(Optimistic Lock),顧名思義,就是很樂(lè)觀,每次去拿數(shù)據(jù)的時(shí)候都認(rèn)為別人不會(huì)修改,所以不會(huì)上鎖,但是在提交更新的時(shí)候會(huì)判斷一下在此期間別人有沒(méi)有去修改。所以悲觀鎖是限制其他線程,而樂(lè)觀鎖是限制自己,雖然他的名字有鎖,但是實(shí)際上不算上鎖,通常為version版本號(hào)機(jī)制,還有CAS算法 .

利用version字段解決并發(fā)問(wèn)題

版本號(hào)機(jī)制就是在數(shù)據(jù)庫(kù)中加一個(gè)字段version當(dāng)作版本號(hào)。那么獲取Article的時(shí)候就會(huì)帶一個(gè)版本號(hào),比如version=1,然后你對(duì)這個(gè)Article一波操作,操作完之后要插入到數(shù)據(jù)庫(kù)了。

校驗(yàn)一下version版本號(hào),發(fā)現(xiàn)在數(shù)據(jù)庫(kù)里對(duì)應(yīng)Article記錄的version=2,這和我手里的版本不一樣啊,說(shuō)明提交的Article不是最新的,那么就不能update到數(shù)據(jù)庫(kù)了,進(jìn)行報(bào)錯(cuò)把,這樣就避免了并發(fā)時(shí)數(shù)據(jù)沖突的問(wèn)題。

?
1
2
3
4
5
public interface ArticleRepository extends JpaRepository<Article, Long> {
    @Modifying
    @Query(value = "update article set content= :content, version = version + 1 where id = :id and version = :version", nativeQuery = true)
    int updateArticleWithVersion(Long id, String content, Long version);
}
?
1
2
3
4
5
6
7
8
9
10
11
12
public void postComment(Long articleId, String content) {
 //get article
    Optional<Article> articleOptional = articleRepository.findById(articleId);
    //update with Optimistic Lock
    int count = articleRepository.updateArticleWithVersion(article.getId(), content, article.getVersion());
  
    if (count == 0) {
        throw new RuntimeException("更新數(shù)據(jù)失敗,請(qǐng)刷新重試");
    }else{
     articleRepository.save(article);
    }
}

利用JPA的@Version版本機(jī)制解決并發(fā)問(wèn)題

有沒(méi)有更優(yōu)雅的方式? 當(dāng)然,必須有,那就是JPA自帶的@Version方式實(shí)現(xiàn)樂(lè)觀鎖。

  • each entity class must have only one version attribute .每個(gè)實(shí)體類只能有一個(gè)@Version字段,不能多
  • it must be placed in the primary table for an entity mapped to several tables . 對(duì)于映射到多個(gè)表的實(shí)體,必須將其放置在主表中
  • type of a version attribute must be one of the following: int, Integer, long, Long, short, Short, java.sql.Timestamp ,

@Version支持的類型必須是以下類型:

  • int
  • Integer
  • long
  • Long
  • short
  • Short
  • java.sql.Timestamp

首先在Article實(shí)體類的version字段上加上@Version注解

?
1
2
3
4
5
6
7
8
9
@Data
@Entity
public class Article{
    @Id
    private Long id; 
  //...... 
    @Version
    private Integer version;
}
?
1
2
3
Article article = entityManager.find(Article.class, id);
entityManager.lock(article , LockModeType.OPTIMISTIC);
entityManager.refresh(article , LockModeType.READ);

什么時(shí)候用悲觀鎖或者樂(lè)觀鎖

悲觀鎖適合寫多讀少的場(chǎng)景。因?yàn)樵谑褂玫臅r(shí)候該線程會(huì)獨(dú)占這個(gè)資源,就適合用悲觀鎖,否則用戶只是瀏覽文章的話,用悲觀鎖就會(huì)經(jīng)常加鎖,增加了加鎖解鎖的資源消耗。

樂(lè)觀鎖適合寫少讀多的場(chǎng)景。由于樂(lè)觀鎖在發(fā)生沖突的時(shí)候會(huì)回滾或者重試,如果寫的請(qǐng)求量很大的話,就經(jīng)常發(fā)生沖突,結(jié)合事務(wù)會(huì)有經(jīng)常的回滾和重試,這樣對(duì)系統(tǒng)資源消耗也是非常大。

所以悲觀鎖和樂(lè)觀鎖沒(méi)有絕對(duì)的好壞,必須結(jié)合具體的業(yè)務(wù)情況來(lái)決定使用哪一種方式。另外在阿里巴巴開(kāi)發(fā)手冊(cè)里也有提到:

如果每次訪問(wèn)沖突概率小于 20%,推薦使用樂(lè)觀鎖,否則使用悲觀鎖。樂(lè)觀鎖的重試次數(shù)不得小于3次。

阿里巴巴建議以沖突概率20%這個(gè)數(shù)值作為分界線來(lái)決定使用樂(lè)觀鎖和悲觀鎖,雖然說(shuō)這個(gè)數(shù)值不是絕對(duì)的,但是作為阿里巴巴各個(gè)大佬總結(jié)出來(lái)的也是一個(gè)很好的參考。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持服務(wù)器之家。

原文鏈接:https://zhengkai.blog.csdn.net/article/details/103086074

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 一级大片在线观看 | 欧美成人免费小视频 | 久久亚洲春色中文字幕久久 | av免播放 | 深夜免费福利视频 | 天天草天天干天天射 | 亚洲成人午夜精品 | 成人高清在线 | 欧美视频在线一区二区三区 | 九九视频在线观看黄 | 欧美特黄特色视频 | 久久精品视频69 | 久久久www视频 | 在线成人精品视频 | 成人在线视频网 | 欧美视频在线一区二区三区 | 精品中文一区 | 中文字幕在线观看二区 | 九色com | 一区二区三区日韩在线观看 | 狠狠干夜夜草 | 久久亚洲精品久久国产一区二区 | 黄色18网站 | 午夜在线小视频 | 日韩精品一区二区在线播放 | 免费看一级片 | 日韩激情 | 久久网站热最新地址4 | 国产成人av在线播放 | 久久精品国产99国产精品澳门 | 天堂成人国产精品一区 | bt 自拍 另类 综合 欧美 | 逼片| 免费黄网站在线播放 | 日本逼逼视频 | 成人免费看片a | 黑人一区二区三区四区五区 | 99精品视频久久精品视频 | 亚洲第五色综合网 | 亚洲最黄视频 | 欧美日韩免费一区 |