Python 基於Redis實現乙個分布式讀寫鎖

2021-10-24 04:27:10 字數 3822 閱讀 5063

1、簡述出現背景

python 基於redis實現乙個簡單的分布式鎖

python 基於redis實現乙個分布式可重入鎖

在前面實現了簡單分布式鎖是用來解決分布式場景下的併發寫資料問題,分布式可重入鎖是用來解決併發場景下同一執行緒下再次或多次獲得鎖的問題。

那麼分布式讀寫鎖又是解決什麼問題的呢?

首先來理解下概念,讀寫鎖其實可以拆分為讀鎖和寫鎖,又稱共享鎖和排它鎖,沒錯,和mysql中的共享鎖、排它鎖幾乎是同乙個東西。那可能就有同學要問了,既然mysql有,還用redis實現幹什麼,因為redis足夠快。

它們的作用分開來講就是:讀鎖允許其他讀鎖存在,可以進行併發的讀資料。寫鎖會阻塞其他的讀鎖和寫鎖,在寫資料時,阻塞所有讀寫操作,目的是盡最大的可能保證資料一致性。

2、簡述原理

簡述一下分布式讀寫鎖實現原理:分為兩種情況,第一種是先加了讀鎖,那麼後面再來的讀鎖,都可以獲得鎖,不影響所有的讀操作,但當出現寫鎖想獲得鎖時,就必須等讀鎖釋放後,才能加上寫鎖,此時便會阻塞所有讀寫操作。第二種是先加了寫鎖,那麼會阻塞所有的讀寫操作,直到寫鎖釋放鎖,才能被其他讀鎖或寫鎖獲得鎖繼續向下執行。

3、**參考

# read_write_lock.py

import time

import threading

import redis

import os, sys

class

readwritelock

(object):

def__init__

(self, cache_key, cache_type, time_out=20)

: self.redis_con = self.__get_redis_con(

) self.cache_key = cache_key

self.cache_type = cache_type

self.time_out = time_out

def__get_redis_con

(self)

: pool = redis.connectionpool(host=

'127.0.0.1'

,port=

6379

) redis_con = redis.redis(connection_pool=pool)

return redis_con

defget_lock

(self, val)

: val = val +

':'+ self.cache_type

while

true

: res = self.redis_con.

set(self.cache_key, val, nx=

true

, ex=self.time_out)

if res:

# 表示獲得鎖成功,跳出迴圈

break

else

:# 此時說明已經存在資料

# 表示等待鎖的過程,但是有一種情況是:如果檢測到鎖為讀鎖,來的操作也是讀操作,那麼不阻塞

if self.cache_type ==

'read'

: check_type =

str(self.redis_con.get(self.cache_key)

.decode())

.split(

':')[1

]if check_type ==

'read'

:break

time.sleep(

0.1)

defdel_lock

(self, val)

: val = val +

':'+ self.cache_type

old_val = self.redis_con.get(self.cache_key)

if old_val == val.encode():

self.redis_con.delete(self.cache_key)

sums =

0def

test_lock

(name, num, val)

:try

:if num %2==

0:lock = readwritelock(

'new_key'

,'write'

)else

: lock = readwritelock(

'new_key'

,'read'

)print

('%s 開始工作'

% name)

print

('%s 準備獲取鎖並加鎖'

% name)

lock.get_lock(val)

print

('%s 得到鎖,繼續工作'

% name)

global sums

if num %2==

0:sums +=

15print

('+++++++++++++++++++寫操作++++++++++++++++'

)else

:print

('**********************讀操作******************'

) time.sleep(2)

print

(sums)

except exception as e:

print

('發生異常:%s'

%str

(e))

finally

:print

('%s 操作完成,準備釋放鎖'

%name)

lock.del_lock(val)

if __name__ ==

'__main__'

: start_time = time.time(

) tasks =

for num in

range(1

,4):

t = threading.thread(target=test_lock, args=

('任務%d'

%num, num,

'lock%d'

%num)

) t.start(

)[item.join(

)for item in tasks]

print

('總耗時:'

, time.time(

)- start_time)

4、執行測試
python read_write_lock.py
結果:

任務1 開始工作

任務1 準備獲取鎖並加鎖

任務2 開始工作

任務2 準備獲取鎖並加鎖

任務3 開始工作

任務3 準備獲取鎖並加鎖

任務2 得到鎖,繼續工作

+++++++++++++++++++寫操作++++++++++++++++

15任務2 操作完成,準備釋放鎖

任務3 得到鎖,繼續工作

**********************讀操作******************

任務1 得到鎖,繼續工作

**********************讀操作******************

15任務3 操作完成,準備釋放鎖

15任務1 操作完成,準備釋放鎖

總耗時: 4.038355827331543

python基於redis實現分布式鎖

我們在開發應用的時候,如果需要對某乙個共享變數進行多執行緒同步訪問的時候,可以使用我們學到的鎖進行處理,並且可以完美的執行,毫無bug!注意這是單機應用,後來業務發展,需要做集群,乙個應用需要部署到幾台機器上然後做負載均衡,大致如下圖 上圖可以看到,變數a存在三個伺服器記憶體中 這個變數a主要體現是...

Python 基於Redis實現乙個簡單的分布式鎖

redis lock.py import redis import time import threading 連線池方式 pool redis.connectionpool host 127.0.0.1 port 6379 redis con redis.redis connection pool...

基於Redis實現的單點登入

背景 每個web應用都有自己的session,那如何在分布式或者集群環境下統一session,即如何實現單點登入,如下圖 解決方案 把session資料存放在redis,統一管理,向外提供服務介面,redis可以設定過期時間,對應session的失效時間 優點 訪問速度快,效率高 無單點故障,可以部...