婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av

主頁 > 知識庫 > 淺談Redis在分布式系統(tǒng)中的協(xié)調(diào)性運用

淺談Redis在分布式系統(tǒng)中的協(xié)調(diào)性運用

熱門標簽:竹間科技AI電銷機器人 百度商家地圖標注怎么做 地圖標注如何即時生效 地圖標注費用 小紅書怎么地圖標注店 最簡單的百度地圖標注 玄武湖地圖標注 西藏教育智能外呼系統(tǒng)價格 太原營銷外呼系統(tǒng)

在分布式系統(tǒng)中,各個進程(本文使用進程來描述分布式系統(tǒng)中的運行主體,它們可以在同一個物理節(jié)點上也可以在不同的物理節(jié)點上)相互之間通常是需要協(xié)調(diào)進行運作的,有時是不同進程所處理的數(shù)據(jù)有依賴關(guān)系,必須按照一定的次序進行處理,有時是在一些特定的時間需要某個進程處理某些事務(wù)等等,人們通常會使用分布式鎖、選舉算法等技術(shù)來協(xié)調(diào)各個進程之間的行為。因為分布式系統(tǒng)本身的復(fù)雜特性,以及對于容錯性的要求,這些技術(shù)通常是重量級的,比如 Paxos 算法,欺負選舉算法,ZooKeeper 等,側(cè)重于消息的通信而不是共享內(nèi)存,通常也是出了名的復(fù)雜和難以理解,當在具體的實現(xiàn)和實施中遇到問題時都是一個挑戰(zhàn)。
Redis 經(jīng)常被人們認為是一種 NoSQL 軟件,但其本質(zhì)上是一種分布式的數(shù)據(jù)結(jié)構(gòu)服務(wù)器軟件,提供了一個分布式的基于內(nèi)存的數(shù)據(jù)結(jié)構(gòu)存儲服務(wù)。在實現(xiàn)上,僅使用一個線程來處理具體的內(nèi)存數(shù)據(jù)結(jié)構(gòu),保證它的數(shù)據(jù)操作命令的原子特性;它同時還支持基于 Lua 的腳本,每個 Redis 實例使用同一個 Lua 解釋器來解釋運行 Lua 腳本,從而 Lua 腳本也具備了原子特性,這種原子操作的特性使得基于共享內(nèi)存模式的分布式系統(tǒng)的協(xié)調(diào)方式成了可能,而且具備了很大的吸引力,和復(fù)雜的基于消息的機制不同,基于共享內(nèi)存的模式對于很多技術(shù)人員來說明顯容易理解的多,特別是那些已經(jīng)了解多線程或多進程技術(shù)的人。在具體實踐中,也并不是所有的分布式系統(tǒng)都像分布式數(shù)據(jù)庫系統(tǒng)那樣需要嚴格的模型的,而所使用的技術(shù)也不一定全部需要有堅實的理論基礎(chǔ)和數(shù)學(xué)證明,這就使得基于 Redis 來實現(xiàn)分布式系統(tǒng)的協(xié)調(diào)技術(shù)具備了一定的實用價值,實際上,人們也已經(jīng)進行了不少嘗試。本文就其中的一些協(xié)調(diào)技術(shù)進行介紹。

signal/wait 操作
在分布式系統(tǒng)中,有些進程需要等待其它進程的狀態(tài)的改變,或者通知其它進程自己的狀態(tài)的改變,比如,進程之間有操作上的依賴次序時,就有進程需要等待,有進程需要發(fā)射信號通知等待的進程進行后續(xù)的操作,這些工作可以通過 Redis 的 Pub/Sub 系列命令來完成,比如:

復(fù)制代碼 代碼如下:

import redis, time
rc = redis.Redis()
def wait( wait_for ):
ps = rc.pubsub()  
ps.subscribe( wait_for )
ps.get_message()
wait_msg = None
while True:
msg = ps.get_message()
if msg and msg['type'] == 'message':
wait_msg = msg
break
time.sleep(0.001)
ps.close()
return wait_msgdef
signal_broadcast( wait_in, data ):
wait_count = rc.publish(wait_in, data)
return wait_count
用這個方法很容易進行擴展實現(xiàn)其它的等待策略,比如 try wait,wait 超時,wait 多個信號時是要等待全部信號還是任意一個信號到達即可返回等等。因為 Redis 本身支持基于模式匹配的消息訂閱(使用 psubscribe 命令),設(shè)置 wait 信號時也可以通過模式匹配的方式進行。
和其它的數(shù)據(jù)操作不同,訂閱消息是即時易逝的,不在內(nèi)存中保存,不進行持久化保存,如果客戶端到服務(wù)端的連接斷開的話也是不會重發(fā)的,但是在配置了 master/slave 節(jié)點的情況下,會把 publish 命令同步到 slave 節(jié)點上,這樣我們就可以同時在 master 以及 slave 節(jié)點的連接上訂閱某個頻道,從而可以同時接收到發(fā)布者發(fā)布的消息,即使 master 在使用過程中出故障,或者到 master 的連接出了故障,我們?nèi)匀荒軌驈?slave 節(jié)點獲得訂閱的消息,從而獲得更好的魯棒性。另外,因為數(shù)據(jù)不用寫入磁盤,這種方法在性能上也是有優(yōu)勢的。
上面的方法中信號是廣播的,所有在 wait 的進程都會收到信號,如果要將信號設(shè)置成單播,只允許其中一個收到信號,則可以通過約定頻道名稱模式的方式來實現(xiàn),比如:
頻道名稱 = 頻道名前綴 (channel) + 訂閱者全局唯一 ID(myid)
其中唯一 ID 可以是 UUID,也可以是一個隨機數(shù)字符串,確保全局唯一即可。在發(fā)送 signal 之前先使用“pubsub channels channel*”命令獲得所有的訂閱者訂閱的頻道,然后發(fā)送信號給其中一個隨機指定的頻道;等待的時候需要傳遞自己的唯一 ID,將頻道名前綴和唯一 ID 合并為一個頻道名稱,然后同前面例子一樣進行 wait。示例如下:

復(fù)制代碼 代碼如下:

import random
single_cast_script="""
local channels = redis.call('pubsub', 'channels', ARGV[1]..'*');
if #channels == 0
then
return 0;
end;
local index= math.mod(math.floor(tonumber(ARGV[2])), #channels) + 1;     
return redis.call( 'publish', channels[index], ARGV[3]); """
def wait_single( channel, myid):
return wait( channel + myid )
def signal_single( channel, data):
rand_num = int(random.random() * 65535)
return rc.eval( single_cast_script, 0, channel, str(rand_num), str(data) )


分布式鎖 Distributed Locks
分布式鎖的實現(xiàn)是人們探索的比較多的一個方向,在 Redis 的官方網(wǎng)站上專門有一篇文檔介紹基于 Redis 的分布式鎖,其中提出了 Redlock 算法,并列出了多種語言的實現(xiàn)案例,這里作一簡要介紹。
Redlock 算法著眼于滿足分布式鎖的三個要素:
安全性:保證互斥,任何時間至多只有一個客戶端可以持有鎖
免死鎖:即使當前持有鎖的客戶端崩潰或者從集群中被分開了,其它客戶端最終總是能夠獲得鎖。
容錯性:只要大部分的 Redis 節(jié)點在線,那么客戶端就能夠獲取和釋放鎖。

鎖的一個簡單直接的實現(xiàn)方法就是用 SET NX 命令設(shè)置一個設(shè)定了存活周期 TTL 的 Key 來獲取鎖,通過刪除 Key 來釋放鎖,通過存活周期來保證避免死鎖。不過這個方法存在單點故障風險,如果部署了 master/slave 節(jié)點,則在特定條件下可能會導(dǎo)致安全性方面的沖突,比如:

  • 客戶端 A 從 master 節(jié)點獲得鎖
  • master 節(jié)點在將 key 復(fù)制到 slave 節(jié)點之前崩潰了
  • slave 節(jié)點提升為新的 master 節(jié)點
  • 客戶端 B 從新的 master 節(jié)點獲得了鎖,而這個鎖實際上已經(jīng)由客戶端 A 所持有,導(dǎo)致了系統(tǒng)中有兩個客戶端在同一時間段內(nèi)持有同一個互斥鎖,破壞了互斥鎖的安全性。

在 Redlock 算法中,通過類似于下面這樣的命令進行加鎖:

復(fù)制代碼 代碼如下:

SET resource_name my_random_value NX PX 30000


這里的 my_random_value 為全局不同的隨機數(shù),每個客戶端需要自己產(chǎn)生這個隨機數(shù)并且記住它,后面解鎖的時候需要用到它。
解鎖則需要通過一個 Lua 腳本來執(zhí)行,不能簡單地直接刪除 Key,否則可能會把別人持有的鎖給釋放了:

復(fù)制代碼 代碼如下:

if redis.call("get",KEYS[1]) == ARGV[1] then return   
redis.call("del",KEYS[1])else return 0end


這個 ARGV[1] 的值就是前面加鎖的時候的 my_random_value 的值。
如果需要更好的容錯性,可以建立一個有 N(N 為奇數(shù))個相互獨立完備的 Redis 冗余節(jié)點的集群,這種情況下,一個客戶端獲得鎖和釋放鎖的算法如下:
先獲取當前時間戳 timestamp_1,以毫秒為單位。
以相同的 Key 和隨機數(shù)值,依次從 N 個節(jié)點獲取鎖,每次獲取鎖都設(shè)置一個超時,超時時限要保證小于所有節(jié)點上該鎖的自動釋放時間,以免在某個節(jié)點上耗時過長,通常都設(shè)的比較短。
客戶端將當前時間戳減去第一步中的時間戳 timestamp_1,計算獲取鎖總消耗時間。只有當客戶端獲得了半數(shù)以上節(jié)點的鎖,而且總耗時少于鎖存活時間,該客戶端才被認為已經(jīng)成功獲得了鎖。
如果獲得了鎖,則其存活時間為開始預(yù)設(shè)鎖存活時間減去獲取鎖總耗時間。
如果客戶端不能獲得鎖,則應(yīng)該馬上在所有節(jié)點上解鎖。
如果要重試,則在隨機延時之后重新去獲取鎖。
獲得了鎖的客戶端要釋放鎖,簡單地在所有節(jié)點上解鎖即可。

Redlock 算法不需要保證 Redis 節(jié)點之間的時鐘是同步的(不論是物理時鐘還是邏輯時鐘),這點和傳統(tǒng)的一些基于同步時鐘的分布式鎖算法有所不同。Redlock 算法的具體的細節(jié)可以參閱 Redis 的官方文檔,以及文檔中列出的多種語言版本的實現(xiàn)。

選舉算法
在分布式系統(tǒng)中,經(jīng)常會有些事務(wù)是需要在某個時間段內(nèi)由一個進程來完成,或者由一個進程作為 leader 來協(xié)調(diào)其它的進程,這個時候就需要用到選舉算法,傳統(tǒng)的選舉算法有欺負選舉算法(霸道選舉算法)、環(huán)選舉算法、Paxos 算法、Zab 算法 (ZooKeeper) 等,這些算法有些依賴于消息的可靠傳遞以及時鐘同步,有些過于復(fù)雜,難以實現(xiàn)和驗證。新的 Raft 算法相比較其它算法來說已經(jīng)容易了很多,不過它仍然需要依賴心跳廣播和邏輯時鐘,leader 需要不斷地向 follower 廣播消息來維持從屬關(guān)系,節(jié)點擴展時也需要其它算法配合。
選舉算法和分布式鎖有點類似,任意時刻最多只能有一個 leader 資源。當然,我們也可以用前面描述的分布式鎖來實現(xiàn),設(shè)置一個 leader 資源,獲得這個資源鎖的為 leader,鎖的生命周期過了之后,再重新競爭這個資源鎖。這是一種競爭性的算法,這個方法會導(dǎo)致有比較多的空檔期內(nèi)沒有 leader 的情況,也不好實現(xiàn) leader 的連任,而 leader 的連任是有比較大的好處的,比如 leader 執(zhí)行任務(wù)可以比較準時一些,查看日志以及排查問題的時候也方便很多,如果我們需要一個算法實現(xiàn) leader 可以連任,那么可以采用這樣的方法:

復(fù)制代碼 代碼如下:

import redis
rc = redis.Redis()
local_selector = 0def master():
global local_selector
master_selector = rc.incr('master_selector')
if master_selector == 1:
 # initial / restarted
local_selector = master_selector
else:
if local_selector > 0: # I'm the master before
if local_selector > master_selector: # lost, maybe the db is fail-overed.  
local_selector = 0
else: # continue to be the master
local_selector = master_selector
if local_selector > 0: # I'm the current master
rc.expire('master_selector', 20) return local_selector > 0


這個算法鼓勵連任,只有當前的 leader 發(fā)生故障或者執(zhí)行某個任務(wù)所耗時間超過了任期、或者 Redis 節(jié)點發(fā)生故障恢復(fù)之后才需要重新選舉出新的 leader。在 master/slave 模式下,如果 master 節(jié)點發(fā)生故障,某個 slave 節(jié)點提升為新的 master 節(jié)點,即使當時 master_selector 值尚未能同步成功,也不會導(dǎo)致出現(xiàn)兩個 leader 的情況。如果某個 leader 一直連任,則 master_selector 的值會一直遞增下去,考慮到 master_selector 是一個 64 位的整型類型,在可預(yù)見的時間內(nèi)是不可能溢出的,加上每次進行 leader 更換的時候 master_selector 會重置為從 1 開始,這種遞增的方式是可以接受的,但是碰到 Redis 客戶端(比如 Node.js)不支持 64 位整型類型的時候就需要針對這種情況作處理。如果當前 leader 進程處理時間超過了任期,則其它進程可以重新生成新的 leader 進程,老的 leader 進程處理完畢事務(wù)后,如果新的 leader 的進程經(jīng)歷的任期次數(shù)超過或等于老的 leader 進程的任期次數(shù),則可能會出現(xiàn)兩個 leader 進程,為了避免這種情況,每個 leader 進程在處理完任期事務(wù)之后都應(yīng)該檢查一下自己的處理時間是否超過了任期,如果超過了任期,則應(yīng)當先設(shè)置 local_selector 為 0 之后再調(diào)用 master 檢查自己是否是 leader 進程。

消息隊列
消息隊列是分布式系統(tǒng)之間的通信基本設(shè)施,通過消息可以構(gòu)造復(fù)雜的進程間的協(xié)調(diào)操作和互操作。Redis 也提供了構(gòu)造消息隊列的原語,比如 Pub/Sub 系列命令,就提供了基于訂閱/發(fā)布模式的消息收發(fā)方法,但是 Pub/Sub 消息并不在 Redis 內(nèi)保持,從而也就沒有進行持久化,適用于所傳輸?shù)南⒓词箒G失了也沒有關(guān)系的場景。
如果要考慮到持久化,則可以考慮 list 系列操作命令,用 PUSH 系列命令(LPUSH, RPUSH 等)推送消息到某個 list,用 POP 系列命令(LPOP, RPOP,BLPOP,BRPOP 等)獲取某個 list 上的消息,通過不同的組合方式可以得到 FIFO,F(xiàn)ILO,比如:

復(fù)制代碼 代碼如下:

import redis
rc = redis.Redis()
def fifo_push(q, data):
 rc.lpush(q, data)
def fifo_pop(q):
return rc.rpop(q)
def filo_push(q, data):
rc.lpush(q, data)
def filo_pop(q):
return rc.lpop(q)


如果用 BLPOP,BRPOP 命令替代 LPOP, RPOP,則在 list 為空的時候還支持阻塞等待。不過,即使按照這種方式實現(xiàn)了持久化,如果在 POP 消息返回的時候網(wǎng)絡(luò)故障,則依然會發(fā)生消息丟失,針對這種需求 Redis 提供了 RPOPLPUSH 和 BRPOPLPUSH 命令來先將提取的消息保存在另外一個 list 中,客戶端可以先從這個 list 查看和處理消息數(shù)據(jù),處理完畢之后再從這個 list 中刪除消息數(shù)據(jù),從而確保了消息不會丟失,示例如下:

復(fù)制代碼 代碼如下:

def safe_fifo_push(q, data):
rc.lpush(q, data)
def safe_fifo_pop(q, cache):
msg = rc.rpoplpush(q, cache) # check and do something on msg    
rc.lrem(cache, 1) # remove the msg in cache list. return msg


如果使用 BRPOPLPUSH 命令替代 RPOPLPUSH 命令,則可以在 q 為空的時候阻塞等待。

您可能感興趣的文章:
  • 基于Redis實現(xiàn)分布式鎖以及任務(wù)隊列
  • redis中使用java腳本實現(xiàn)分布式鎖
  • Redis上實現(xiàn)分布式鎖以提高性能的方案研究
  • Redis數(shù)據(jù)庫中實現(xiàn)分布式鎖的方法
  • 詳解Java如何實現(xiàn)基于Redis的分布式鎖
  • 在Redis數(shù)據(jù)庫中實現(xiàn)分布式速率限制的方法
  • redis 隊列操作的例子(php)
  • php中使用redis隊列操作實例代碼
  • 詳解Redis用鏈表實現(xiàn)消息隊列
  • Redis實現(xiàn)分布式隊列淺析

標簽:唐山 香港 澳門 贛州 廣東 林芝 揚州 景德鎮(zhèn)

巨人網(wǎng)絡(luò)通訊聲明:本文標題《淺談Redis在分布式系統(tǒng)中的協(xié)調(diào)性運用》,本文關(guān)鍵詞  淺談,Redis,在,分布式,系統(tǒng),;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請?zhí)峁┫嚓P(guān)信息告之我們,我們將及時溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《淺談Redis在分布式系統(tǒng)中的協(xié)調(diào)性運用》相關(guān)的同類信息!
  • 本頁收集關(guān)于淺談Redis在分布式系統(tǒng)中的協(xié)調(diào)性運用的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av
    欧美电视剧在线观看完整版| 国产精品自拍av| 日本欧美一区二区在线观看| 成人污污视频在线观看| 91精品午夜视频| 国产精品丝袜在线| 一区二区三区日本| 日韩一区二区在线看| 国产日韩精品一区二区三区 | 日韩精品一二区| 精品一区二区在线观看| 欧美日韩国产高清一区| 久久夜色精品国产噜噜av | 丁香婷婷综合激情五月色| 日韩你懂的在线播放| 久久精品免费观看| 国产亚洲福利社区一区| 盗摄精品av一区二区三区| 国产精品久久久久久久久搜平片 | 丁香五精品蜜臀久久久久99网站| 久久久99免费| 99久久精品免费| 亚洲电影你懂得| 精品日韩av一区二区| 国产suv精品一区二区6| 日韩毛片一二三区| 欧美日韩成人激情| 国产精品影视在线| 亚洲国产视频直播| 久久综合九色欧美综合狠狠| 久久综合色播五月| 一区二区三区高清不卡| 日韩色视频在线观看| 在线播放国产精品二区一二区四区| 国产精品18久久久久久久久| 亚洲男帅同性gay1069| 欧美日韩大陆在线| 成人小视频在线| 图片区小说区区亚洲影院| 国产亚洲成年网址在线观看| 欧美丝袜丝交足nylons图片| 久久精品国产99久久6| 中文字幕视频一区| 国产亚洲精品精华液| 日韩欧美中文一区| 欧美色男人天堂| 色婷婷国产精品| 成年人网站91| 成人综合激情网| 国产主播一区二区三区| 日韩精品国产欧美| 午夜精品在线视频一区| 亚洲色欲色欲www在线观看| 久久嫩草精品久久久精品| 8x福利精品第一导航| 色综合久久久久综合体| 成a人片国产精品| 国产成人综合网站| 国产传媒久久文化传媒| 国产乱子伦视频一区二区三区| 午夜天堂影视香蕉久久| 亚洲成av人片在线观看| 亚洲一区二区三区小说| 一区二区三区中文字幕| 成人午夜又粗又硬又大| 韩国毛片一区二区三区| 麻豆久久久久久| 色偷偷88欧美精品久久久| 精品一区二区精品| 亚洲男人的天堂在线aⅴ视频| 日韩欧美中文一区二区| 黄色资源网久久资源365| 极品美女销魂一区二区三区 | 麻豆精品视频在线观看视频| 精品88久久久久88久久久| 国产乱子轮精品视频| 婷婷久久综合九色综合绿巨人| 国产精品三级在线观看| 精品成人一区二区| 91麻豆精品国产91| 在线观看国产91| 成人激情午夜影院| 国产传媒欧美日韩成人| 韩国毛片一区二区三区| 奇米亚洲午夜久久精品| 婷婷综合久久一区二区三区| 日韩av一级电影| 香蕉久久一区二区不卡无毒影院| 日韩一区中文字幕| 国产精品麻豆欧美日韩ww| 久久久精品人体av艺术| 久久一日本道色综合| 久久综合狠狠综合| 欧美成人r级一区二区三区| 99re在线视频这里只有精品| 高清视频一区二区| 高潮精品一区videoshd| 成人性生交大片免费看在线播放| 精久久久久久久久久久| av电影在线观看一区| 精品视频999| 3atv一区二区三区| 成人综合激情网| 亚洲国产中文字幕| 亚洲图片欧美综合| 舔着乳尖日韩一区| 亚洲一区二区五区| 丰满放荡岳乱妇91ww| 99久久精品免费看国产免费软件| 色综合色综合色综合| 国产精品视频九色porn| 亚洲人成电影网站色mp4| 精品国产三级电影在线观看| 亚洲一区在线观看免费 | 麻豆91在线观看| 国产精品自拍在线| 色狠狠一区二区| 91.com视频| 国产亚洲精品中文字幕| 久久国产麻豆精品| 91免费视频网址| 国产精品丝袜在线| 亚洲成人黄色影院| 欧美影院午夜播放| 久久久久久久久久电影| 中文字幕在线观看一区| 午夜不卡在线视频| 成人高清视频在线| jizz一区二区| 国产欧美视频在线观看| 午夜视频一区二区三区| 国产·精品毛片| 884aa四虎影成人精品一区| 精品国产91乱码一区二区三区| 国产精品欧美久久久久一区二区| 一区二区三区精品久久久| 亚洲最新在线观看| 色婷婷av一区二区三区大白胸| 日韩一区二区电影在线| 中文字幕一区二区三区不卡在线 | 欧美精品在线观看一区二区| 欧美性猛交xxxx乱大交退制版 | 精品日韩一区二区| 亚洲男人都懂的| 麻豆精品在线视频| 精品国产麻豆免费人成网站| 亚洲免费观看高清完整版在线| 久久99精品久久久久婷婷| 91黄色激情网站| 国产欧美日韩卡一| 国内精品免费在线观看| 91麻豆精品国产91久久久| 一区二区三区免费在线观看| 美腿丝袜亚洲综合| 久久精品人人做| 国内精品久久久久影院色 | 成人性生交大片免费看在线播放 | 国产欧美一区二区精品秋霞影院| 日本在线不卡视频| 久久久无码精品亚洲日韩按摩| 亚洲午夜免费视频| 国产精品中文字幕一区二区三区| 久久综合九色综合97_久久久| 一区二区三区毛片| 丁香婷婷深情五月亚洲| 欧美v日韩v国产v| 日本不卡一二三| 欧美精品日韩一本| 亚洲第一主播视频| 欧美午夜片在线观看| 亚洲精品成人在线| 91影院在线免费观看| 日韩精品一区二区三区在线观看| 亚洲va欧美va人人爽| 欧美色网一区二区| 亚洲一二三四久久| 欧美日本视频在线| 日韩av在线发布| 欧美精品一区二区久久婷婷| 国产一区999| 亚洲视频一区在线观看| 麻豆成人在线观看| 夜夜操天天操亚洲| 欧美一级欧美三级| 成人免费在线观看入口| 日韩免费看的电影| 日本中文一区二区三区| 在线看一区二区| 国产美女视频91| 国产精品久久久久久久久久免费看| 欧美日韩在线播放三区| 日本不卡一二三| 亚洲图片欧美综合| 成人高清伦理免费影院在线观看| 成人免费视频一区二区| 捆绑变态av一区二区三区| 韩国视频一区二区| 国精产品一区一区三区mba桃花| 欧美色男人天堂| 欧美激情中文字幕一区二区|