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

Redis并發(fā)訪問問題詳細講解

 更新時間:2022年12月02日 10:25:50   作者:肥肥技術(shù)宅  
本文主要介紹了Redis如何應(yīng)對并發(fā)訪問,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

前言

我們在使用Redis的過程中,難免會遇到并發(fā)訪問及數(shù)據(jù)更新的問題。但很多場景對數(shù)據(jù)的并發(fā)修改是很敏感的,比如庫存數(shù)據(jù)如果沒有做好并發(fā)讀取和更新的版本控制,就會導(dǎo)致嚴重的業(yè)務(wù)問題。今天就來說說應(yīng)該如何做好并發(fā)訪問及數(shù)據(jù)更新問題。

什么場景需要控制并發(fā)訪問

需要控制并發(fā)訪問,說明這些并發(fā)的訪問可能會對其他的訪問造成影響。比如上面提到的庫存問題,若同一時期有多個客戶端訪問商品A的庫存數(shù)據(jù),并且可能要更更新庫存數(shù)據(jù),這時候就需要對并發(fā)訪問進行控制了。

說到底,并發(fā)訪問需要控制的就是對數(shù)據(jù)的更新動作。 一般來說,客戶端要進行數(shù)據(jù)更新時可分為2個步驟:

  • 客戶端讀取Redis數(shù)據(jù)到本地。
  • 確認數(shù)據(jù)后,修改Redis的數(shù)據(jù)。

單個訪問來看,這個過程并沒什么問題。但是并發(fā)多了,一分為二的過程就會造成數(shù)據(jù)錯誤的問題。這里還是用庫存的例子來說:

  • 時間a::客戶端1讀取到庫存=10,我們需要對庫存+1=11的操作。
  • 時間b:客戶端2讀取到的庫存也是10,這次要對庫存-1=9的操作。
  • 時間c:客戶端1將+1后的值11寫回到Redis中。
  • 時間d:客戶端2將-1后的值9寫回到Redis中。

這樣下來,很明顯能發(fā)現(xiàn)庫存數(shù)據(jù)錯了。10+1-1 = 10,正確庫存是10,而上述場景最后為9。

由此可見,這個一分為二的操作不具有原子性,從而產(chǎn)生了錯誤的結(jié)果。類型這種場景很多,因此我們需要對這些并發(fā)訪問的場景加以控制。

并發(fā)訪問的控制方法

Redis并發(fā)訪問的控制,總的來說有2種方式。分別是加入鎖機制和讓一系列操作原子化。

1、加入鎖機制

首先第一點,加入鎖機制是很常見的解決方案。簡單來說就是一個客戶端訪問數(shù)據(jù)之前,先要獲取鎖,等數(shù)據(jù)操作完之后再解鎖。而在這個客戶端擁有鎖的過程中,其他客戶端如果也想訪問修改該數(shù)據(jù),必須得等鎖釋放了之后,獲取到了鎖才行。

加鎖這個方案是可以解決并發(fā)訪問的數(shù)據(jù)準確問題,但放在redis這個場景中并不是很好。首先,Redis作為緩存本身并發(fā)訪問就很多,頻繁的加鎖解鎖,會大大降低redis的訪問性能;然后,Redis的客戶端在要加鎖時,需要用到分布式鎖。我們又得用額外的精力去維護這個分布式鎖。

2、操作原子化

操作原子化,也就是讓要執(zhí)行的一系列動作都保持原子性操作。它的優(yōu)點就是不需要加入額外的鎖機制。并發(fā)的數(shù)據(jù)準確性達到了,對Redis的性能也不會有太大的影響。

Redis要實現(xiàn)原子操作,總結(jié)有2種方式:

  • 單命令操作:也就是Redis中的INCR、HINCRBY等命令,直接將簡單的加減操作合成一個命令執(zhí)行;
  • Lua腳本:借助Lua腳本,讓多個操作在Lua腳本上實現(xiàn)原子性操作。

1.單命令操作

首先,單命令操作,將數(shù)值的加減直接用Redis命令來執(zhí)行。像string的加減可用INCR、DECR操作,hash列表field的加減可用HINCRBY操作。

比如下面截圖,兩個客戶端在不同時刻讀取的linux_pids a值為4,各自+1、-1后a值為4。結(jié)果是正確的。

由此可見,用Redis的INCR、DECR等命令可以解決數(shù)值簡單增減的并發(fā)場景。但如果我們對數(shù)據(jù)的更新不僅僅是簡單的加減操作時,Redis的這些命令就無能為力了。此時我們可以考慮另一種方案:Lua腳本。

2.Lua腳本

Lua語言是由C寫的,因此支持多平臺和系統(tǒng)。從Redis2.6開始,Redis就內(nèi)置了Lua解釋器,我們能直接用Redis客戶端來執(zhí)行l(wèi)ua腳本。

我們可以將需要執(zhí)行的一系列操作用Lua腳本寫好,然后用Redis執(zhí)行它。Lua腳本的方法能保證原子性操作的原因是:Redis會將Lua腳本一次性執(zhí)行,也就是說執(zhí)行Lua腳本是0-1的操作,要么成功,要么失敗??梢岳斫獬蒑ySQL的事務(wù)特性。

Redis使用lua腳本有2種方式:

  • 客戶端中使用:用到script load腳本內(nèi)容、evalsha等命令
  • 執(zhí)行直接執(zhí)行l(wèi)ua腳本

我們一般用第二種方式來執(zhí)行。

客戶端使用方法:

先用script load加載腳本命令,再用evalsha執(zhí)行加載得到的sha1值。

127.0.0.1:6379> script load "return 'hello'"
"1b936e3fe509bcbc9cd0664897bbe8fd0cac101b"
127.0.0.1:6379> evalsha "1b936e3fe509bcbc9cd0664897bbe8fd0cac101b" 0
"hello"

再來看看Redis使用Lua腳本的語法:

redis-cli --eval {lua_path} KEYS[1] KEYS[2]... , ARGV[1] ARGV[2]...
 
--eval:          執(zhí)行l(wèi)ua腳本的命令
{lua_path}:         lua腳本的路徑
KEYS[1] KEYS[2]:       lua腳本中要操作的redis鍵,我們可以在lua腳本中用KEYS[1],KEYS[2],KEYS[3]指定多個
ARGV[1] ARGV[2]:    傳入到lua腳本的參數(shù),在腳本中用ARGV[1],ARGV[2]...來獲取。

Redis使用lua腳本的場景很多,最經(jīng)典的案例當(dāng)屬利用lua來控制某個IP的訪問頻率了。比如說需要防止惡意訪問網(wǎng)站的行為,我們規(guī)定1分鐘內(nèi)訪問次數(shù)不能超過30次,實現(xiàn)的方法有很多,比如說漏桶方案、令牌桶方案,但使用最多的還是Redis+lua的分布式限流方案。

我們用lua腳本(test_lua.script)來簡單實現(xiàn)一下上述功能,就是1分鐘內(nèi)若訪問次數(shù)超過30,直接攔截,否則訪問次數(shù)+1:

-- 限流的key
local limit_key = KEYS[1]
-- 限流次數(shù)
local limit_nums = 30
-- 當(dāng)前訪問次數(shù)
local current_num = tonumber(redis.call('get', limit_key) or 0)
-- 超出限流次數(shù)
if current_num + 1 > limit_num
    then
    return '超出訪問次數(shù)'
-- 沒有超出限流數(shù),訪問次數(shù)+1
else
  redis.call("INCRBY", limit_key, "1")
  -- 第一次訪問,設(shè)置過期時間
  if current_num == 0 then
    redis.call("expire", limit_key, "60")
  return current + 1
end

用Redis執(zhí)行,命令如下:

redis-cli --eval test_lua.script limit_key

小結(jié)

本文介紹了Redis并發(fā)訪問的控制問題,以及如何保證并發(fā)操作的原子化。原子化操作可通過單命令操作和Lua腳本的方式實現(xiàn)。我們在應(yīng)對相關(guān)問題時,可根據(jù)需要選擇對應(yīng)方案解決之。

到此這篇關(guān)于Redis并發(fā)訪問問題詳細講解的文章就介紹到這了,更多相關(guān)Redis并發(fā)訪問內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 通過kubesphere部署redis的方法

    通過kubesphere部署redis的方法

    這篇文章主要介紹了通過kubesphere部署redis的方法,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-11-11
  • Redis?HyperLogLog數(shù)據(jù)統(tǒng)計輕量級解決方案詳解

    Redis?HyperLogLog數(shù)據(jù)統(tǒng)計輕量級解決方案詳解

    這篇文章主要為大家介紹了Redis?HyperLogLog數(shù)據(jù)統(tǒng)計輕量級解決方案詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-12-12
  • 使用Redis實現(xiàn)延時任務(wù)的解決方案

    使用Redis實現(xiàn)延時任務(wù)的解決方案

    這篇文章主要介紹了使用Redis實現(xiàn)延時任務(wù)的解決方案,本文給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-08-08
  • 淺談Redis變慢的原因及排查方法

    淺談Redis變慢的原因及排查方法

    本文主要介紹了淺談Redis變慢的原因及排查方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • 在redisCluster中模糊獲取key方式

    在redisCluster中模糊獲取key方式

    這篇文章主要介紹了在redisCluster中模糊獲取key方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • 徹底弄懂Redis的LRU淘汰策略

    徹底弄懂Redis的LRU淘汰策略

    本文主要介紹了LRU淘汰策略以及實現(xiàn)一個LRU算法,文章會結(jié)合圖解循序漸進的講解,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • 一文了解發(fā)現(xiàn)并解決Redis熱key與大key問題

    一文了解發(fā)現(xiàn)并解決Redis熱key與大key問題

    熱key是服務(wù)端的常見問題,本文主要介紹Redis熱key與大key問題的解決方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-05-05
  • Redis中事件驅(qū)動模型示例詳解

    Redis中事件驅(qū)動模型示例詳解

    Redis這個數(shù)據(jù)庫相信不用過多介紹了,大家應(yīng)該都知道,下面這篇文章主要給大家介紹了關(guān)于Redis中事件驅(qū)動模型的相關(guān)資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-03-03
  • Redis?腳本和連接命令示例詳解

    Redis?腳本和連接命令示例詳解

    Redis腳本是一種可以實現(xiàn)復(fù)雜任務(wù)的腳本語言,可以用來快速履行復(fù)雜任務(wù),靈活處理數(shù)據(jù)管理和管理復(fù)雜的利用場景,這篇文章主要介紹了Redis?腳本和連接命令,需要的朋友可以參考下
    2023-09-09
  • redis的主從配置方法詳解

    redis的主從配置方法詳解

    今天為大家介紹下linux系統(tǒng)下redis的主從配置方法,Linux系統(tǒng)下的redis的主從配置方法非常簡單下面是具體的操作步驟
    2018-09-09

最新評論