在分散式大量資料收集過程中,信源的管理尤其重要。為了確保同一任務在同一時間只能被一個採集器處理,必須確保任務調度的獨特性。通常我們在進行分散式資料收集時,一般情況下都會有一個調度模組,其主要的職責就是負責採集任務的分發,同時確保任務的唯一性。
由於是分散式,涉及多台伺服器(多機),每台伺服器又涉及到多個採集器(多進程),每個採集器又有可能涉及多執行緒,所以,任務調度模組中的鎖定機制顯得特別重要。根據應用的實作架構不同,鎖的實作方式通常可以分為以下幾種型別
#如果處理程序是單行程多執行緒的,在python下,就可以使用threading 模組的Lock 物件來限制對共享變數的同步訪問,實現線程安全。
單機多進程的情況,在 python 下,可以使用 multiprocessing 的 Lock 物件來處理。
多機多進程部署的情況,就得依賴一個第三方元件(儲存鎖定物件)來實現一個分散式的同步鎖了。
由於調度模組是多機多進程多執行緒的處理機制,所以符合第三種方式。
分散式鎖定實作方式
目前主流的分散式鎖定實作方式有以下幾種:
基於資料庫來實現,如mysql
基於快取來實現,如redis
基於zookeeper 來實作
#每種實作方式各有千秋,綜合考量,Redis是最適合的選擇。主要原因是:
redis 是基於記憶體來操作,存取速度比資料庫快,在高並發下,加鎖之後的效能不會下降太多
redis 可以設定鍵值的生存時間(TTL)
#redis 的使用方式簡單,整體實作開銷小
#但是,使用redis 實作的分散鎖定還需要具備以下幾個條件:
同一個時刻只能有一個執行緒佔有鎖,其他執行緒必須等待直到鎖被釋放
鎖定的操作必須滿足原子性
不會發生死鎖,例如已取得鎖定的執行緒在釋放鎖定之前突然異常退出,導致其他執行緒會一直在循環等待鎖被釋放
#鎖定的新增和釋放必須由同一個執行緒來設定
#我們使用redis 來實作一個分散式同步鎖,來確保資料的一致性,需滿足一下特點:
滿足互斥性,同一個時刻只能有一個線程可以獲取鎖
利用redis 的ttl 來確保不會出現死鎖,但同時也會帶來由於鎖過期引發的多執行緒同時佔有鎖的問題,需要我們合理設定鎖的過期時間來避免
利用鎖的唯一性來確保不會出現誤刪鎖的情況
我在實際操作過程中,把調度模組從整個採集系統中拆離了出來,基於Java客戶端Jredis(JRedis是一個高效能的Java客戶端,用來連接到Redis分散式雜湊鍵-值資料庫。一個獨立的服務,使用Spring Boot實現了同步和非同步功能。以便其他各個採集器,透過HTTP方式請求所要處理的採集任務。其處理過程大致如下:
採集器透過HTTP方式,向調度中心發送任務請求;
public static List,否則出現某些不可知的異常時,可能會導致鎖定無法釋放,擷取器一直無法取得到擷取任務的情況。
以上是基於Redis分散式鎖的任務調度怎麼實現的詳細內容。更多資訊請關注PHP中文網其他相關文章!