欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

使用Redis解決高并發(fā)方案及思路解讀

 更新時間:2023年03月31日 09:08:06   作者:WINGZINGLIU  
這篇文章主要介紹了使用Redis解決高并發(fā)方案及思路,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

NoSQL

Not Only SQL的簡稱。NoSQL是解決傳統(tǒng)的RDBMS在應(yīng)對某些問題時比較乏力而提出的。

即非關(guān)系型數(shù)據(jù)庫,它們不保證關(guān)系數(shù)據(jù)的ACID特性,數(shù)據(jù)之間一般沒有關(guān)聯(lián),在擴(kuò)展上就非常容易實現(xiàn),并且擁有較高的性能。

Redis

redis是nosql的典型代表,也是目前互聯(lián)網(wǎng)公司的必用技術(shù)。

redis是鍵值(Key-Value)存儲數(shù)據(jù)庫,主要會使用到哈希表。大多數(shù)時候是直接以緩存的形式被使用,使得請求不直接訪問到磁盤,所以效率方面是很不錯的,完全能滿足中小型企業(yè)的使用需求。

常用數(shù)據(jù)類型

  • 字符串string
  • 散列hash
  • 列表list
  • 集合sets
  • 有序集合sort set

使用頻率上string和hash會高一些,各個類型有各自的操作命令,無非增刪改查,具體的命令后面我會整理一份。

痛點(diǎn)

web應(yīng)用在眾多請求同時發(fā)生時,可能會導(dǎo)致數(shù)據(jù)讀取、存儲上出現(xiàn)錯誤,即發(fā)生臟讀、臟數(shù)據(jù)生成。

在分布式項目下,會出現(xiàn)更多的問題。

思路

并發(fā)時,本質(zhì)其實就是多個請求同時進(jìn)來了,沒辦法正確的去進(jìn)行處理。

可以將所有的請求放在 一個隊列,讓請求們按照一個順序,挨個進(jìn)來執(zhí)行業(yè)務(wù)邏輯。目前成熟的解決方案就是使用消息隊列,下次我會整理一篇消息隊列處理高并發(fā)的;

還有一個方法是直接將并行轉(zhuǎn)為串行,Java提供了synchronized,即同步,不過這個在效率要求比較苛刻的地方 或者 分布式項目下還是不太合適的方案,這里就引出了使用redis來實現(xiàn)分布式鎖,從而解決并發(fā)問題。

分布式鎖

在分布式項目中,使用一個唯一、通用、效率高的標(biāo)識,來表示上鎖和解鎖。

redis實現(xiàn)起來很簡單,即對一個key是否存在來表示是否上鎖、是否解鎖。

以string類型舉例:

Integer stock = goodsMapper.getStock();
if (stock > 0) {
? ? stock =- 1;
? ? goodsMapper.updateStock(stock);
}

以上是最簡單的秒殺偽代碼,我們嘗試用redis實現(xiàn)分布式鎖。

// 這里是錯誤代碼,只是一個思考過程,請耐心看完哦
String key = "REDIS_DISTRIBUTION_LOCKER"; // 分布式鎖名稱
String value = jedisUtils.get(key);
if (value != null) { // 未上鎖
? ? // wingzingliu
? ? jedisUtils.set(key, 1); // 上鎖
? ? Integer stock = goodsMapper.getStock();
? ? if (stock > 0) {
? ? ? ? stock =- 1;
? ? ? ? goodsMapper.updateStock(stock);
? ? ? ? jedisUtils.del(key); // 釋放鎖
? ? }
}

以上代碼可能會出現(xiàn)一個問題,就是當(dāng)同時多個請求進(jìn)來,某次多個請求都拿到value為空,線程A進(jìn)入if 走到// wingzingliu這里的時候,還未上鎖,其他請求也進(jìn)來了,這樣就會出現(xiàn)臟數(shù)據(jù)了。

這里的代碼問題就是出在沒有考慮原子性問題。

所以我們要使用到redis的一個setNx命令,本質(zhì)也是設(shè)置值,但是這是一個原子操作,執(zhí)行之后會返回是否設(shè)置成功。

redis> SETNX job "programmer" ? ?# job 設(shè)置成功
(integer) 1
?
redis> SETNX job "code-farmer" ? # 嘗試覆蓋 job ,失敗
(integer) 0
?
redis> GET job ? ? ? ? ? ? ? ? ? # 沒有被覆蓋
"programmer"

重點(diǎn)關(guān)注 當(dāng)有值時,會失敗,返回0。所以我們的代碼會改造成以下這個樣子。

// 這里是錯誤代碼,只是一個思考過程,請耐心看完哦
String key = "REDIS_DISTRIBUTION_LOCKER"; // 分布式鎖名稱
Long result = jedisUtils.setNx(key, 1);
if (result > 0) { // 上鎖成功,進(jìn)入邏輯
? ? // wingzingliu1
? ? Integer stock = goodsMapper.getStock();
? ? if (stock > 0) {
? ? ? ? stock =- 1;
? ? ? ? goodsMapper.updateStock(stock);
?
? ? ? ? System.out.println("購買成功!");
? ? } else {
? ? ? ? System.out.println("沒有庫存了!");
? ? }
? ? // wingzingliu2
? ? jedisUtils.del(key); // 釋放鎖
}

以上我們就可以保證原子性,能正確的按照順序去處理。

可是還有一個隱藏的問題,就是當(dāng)某個線程執(zhí)行上鎖成功后,在wingzingliu1到wingzingliu2之間時,程序拋異常了,那么程序終止了,就無法釋放鎖,其他線程也都進(jìn)不來了。

解決方案是加上try catch finally塊,在finally里面去釋放鎖。

可是那如果是宕機(jī)呢?上鎖之后宕機(jī)了,finally里面的依然不會執(zhí)行,鎖沒有得到釋放,不手動處理的情況下,以后所有線程也無法進(jìn)入。

所以引入了redis的過期時間,到了某個時間自動解鎖。

// 這里是不夠完善的代碼,請耐心看完哦
try {
? ? String key = "REDIS_DISTRIBUTION_LOCKER"; // 分布式鎖名稱
? ? Long result = jedisUtils.setNx(key, 1, 30); // 假設(shè)處理邏輯需要20s左右,設(shè)置了30秒自動過期
? ? if (result > 0) { // 上鎖成功,進(jìn)入邏輯
? ? ? ? Integer stock = goodsMapper.getStock();
? ? ? ? if (stock > 0) {
? ? ? ? ? ? stock =- 1;
? ? ? ? ? ? goodsMapper.updateStock(stock);
?
? ? ? ? ? ? System.out.println("購買成功!");
? ? ? ? } else {
? ? ? ? ? ? System.out.println("沒有庫存了!");
? ? ? ? }
? ? }
} catch (Exception e) {
? ??
} finally {
? ? jedisUtils.del(key); // 釋放鎖
}

以上是比較完善的分布式鎖了,但是還有一個小瑕疵,就是假設(shè)某一次請求A處理的很慢,預(yù)計20s但是跑了35s,到了30s的時候鎖過期了,其他請求就自然進(jìn)來了。

這不僅僅會導(dǎo)致一次并行,當(dāng)請求A處理完時,依然會執(zhí)行釋放鎖,這實際上是下一個線程上的鎖。以此類推,整個并發(fā)控制就亂了。

理論上可以設(shè)置一個更大的key過期時間,但是并不是最好的解決方案。這里就引出一個概念:鎖續(xù)命。

鎖續(xù)命

如其名,給鎖續(xù)命。實現(xiàn)就是 當(dāng)鎖快過期的時候,去延長鎖的時間。假設(shè)一個30s的鎖,每個10s去檢測一下,鎖是否還在 如果在就重新延長至30s。這樣就避免掉了上面的這個可能出現(xiàn)的問題。

這里使用一個定時任務(wù),周期性的調(diào)用即可。

擴(kuò)展

剛剛對key設(shè)置的value是1,其實能使用請求ID來進(jìn)行保存,這樣就能知道鎖是由哪個請求上的,在解鎖的時候 也可以避免解鎖了其他線程上的鎖。具體由前端傳遞,或者由服務(wù)端以某種規(guī)則生成都可以。

結(jié)語

至此我們就使用redis,一步一步的解決了在分布式項目下的并發(fā)問題。redis不是唯一的解決方案,但是對于大部分互聯(lián)網(wǎng)公司來說,是一個很成熟、性能不錯、便捷的方案。

還可以使用synchronized(非分布式項目)、mq 、zookeeper等方案去實現(xiàn)分布式鎖 以 解決高并發(fā)問題。

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 關(guān)于redis狀態(tài)監(jiān)控和性能調(diào)優(yōu)詳解

    關(guān)于redis狀態(tài)監(jiān)控和性能調(diào)優(yōu)詳解

    Redis是一種高級key-value數(shù)據(jù)庫。它跟memcached類似,不過數(shù)據(jù)可以持久化,而且支持的數(shù)據(jù)類型很豐富。有字符串,鏈表、哈希、集合和有序集合5種。下面這篇文章主要給大家介紹了關(guān)于redis狀態(tài)監(jiān)控和性能調(diào)優(yōu)的相關(guān)資料,需要的朋友可以參考下。
    2017-09-09
  • Redisson 主從一致性問題詳解

    Redisson 主從一致性問題詳解

    這篇文章主要為大家介紹了Redisson 主從一致性問題詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • 淺談Redis處理接口冪等性的兩種方案

    淺談Redis處理接口冪等性的兩種方案

    本文主要介紹了淺談Redis處理接口冪等性的兩種方案,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • Linux下Redis安裝使用教程

    Linux下Redis安裝使用教程

    這篇文章主要為大家詳細(xì)介紹了Linux下Redis安裝使用教程,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-09-09
  • redis緩存一致性延時雙刪代碼實現(xiàn)方式

    redis緩存一致性延時雙刪代碼實現(xiàn)方式

    這篇文章主要介紹了redis緩存一致性延時雙刪代碼實現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • 談?wù)凴edis分布式鎖的正確實現(xiàn)方法

    談?wù)凴edis分布式鎖的正確實現(xiàn)方法

    這篇文章主要給大家介紹了關(guān)于Redis分布式鎖的正確實現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Redis具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • 徹底弄懂Redis的LRU淘汰策略

    徹底弄懂Redis的LRU淘汰策略

    本文主要介紹了LRU淘汰策略以及實現(xiàn)一個LRU算法,文章會結(jié)合圖解循序漸進(jìn)的講解,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • 在redis中防止消息丟失的機(jī)制

    在redis中防止消息丟失的機(jī)制

    在項目中,由于網(wǎng)絡(luò)問題,我們很難保證生產(chǎn)者發(fā)送的消息能100%到達(dá)消息隊列服務(wù)器,也就是說有消息丟失的可能性,因 此,生產(chǎn)者就必須具有消息丟失檢測和重發(fā)機(jī)制,這篇文章主要介紹了如何在redis中防止消息丟失,需要的朋友可以參考下
    2023-02-02
  • 詳解Redis高效恢復(fù)策略內(nèi)存快照與AOF

    詳解Redis高效恢復(fù)策略內(nèi)存快照與AOF

    這篇文章主要為大家介紹了Redis高效恢復(fù)策略內(nèi)存快照與AOF及對比詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • Redis通過scan查找不過期的 key(方法詳解)

    Redis通過scan查找不過期的 key(方法詳解)

    SCAN 命令是一個基于游標(biāo)的迭代器,每次被調(diào)用之后, 都會向用戶返回一個新的游標(biāo), 用戶在下次迭代時需要使用這個新游標(biāo)作為 SCAN 命令的游標(biāo)參數(shù), 以此來延續(xù)之前的迭代過程,對Redis scan 查找 key相關(guān)知識感興趣的朋友一起看看吧
    2021-08-08

最新評論