概述
Redis是一個開源,先進的key-value儲存,並用於構建高效能,可擴充的Web應用程式的完美解決方案。
Redis從它的許多競爭繼承來的三個主要特點:
Redis資料庫完全在記憶體中,使用磁碟僅用於持久性。
相比許多索引值資料存放區,Redis擁有一套較為豐富的資料類型。
Redis可以將資料複製到任意數量的從伺服器。
Redis 優勢
異常快速:Redis的速度非常快,每秒能執行約11萬集合,每秒約81000+條記錄。
支援豐富的資料類型:Redis支援最大多數開發人員已經知道像列表,集合,有序集合,散列資料類型。這使得它非常容易解決各種各樣的問題,因為我們知道哪些問題是可以處理通過它的資料類型更好。
操作都是原子性:所有Redis操作是原子的,這保證了如果兩個用戶端同時訪問的Redis伺服器將獲得更新後的值。
多功能工具 + 生產力:Redis是一個多實用的工具,可以在多個用例如緩衝,訊息,隊列使用(Redis原生支援發布/訂閱),任何短暫的資料,應用程式,如Web應用程式工作階段,網頁命中計數等。
步入主題:
Redis作為記憶體資料庫的一個典型代表,已經在很多應用情境中被使用,這裡僅就Redis的pub/sub功能來說說怎樣通過此功能來實現一個簡單的作業調度系統。這裡只是想展現一個簡單的想法,所以還是有很多需要考慮的東西沒有包括在這個例子中,比如錯誤處理,持久化等。
下面是實現上的想法
MyMaster:叢集的master節點程式,負責產生作業,派發作業和擷取執行結果。
MySlave:叢集的計算節點程式,每個計算節點一個,負責擷取作業並運行,並將結果發送會master節點。
channel CHANNEL_DISPATCH:每個slave節點訂閱一個channel,比如“CHANNEL_DISPATCH_[idx或機器名]”,master會向此channel中publish被dispatch的作業。
channel CHANNEL_RESULT:用來儲存作業結果的channel,master和slave共用此channel,master訂閱此channel來擷取作業運行結果,每個slave負責將作業執行結果發布到此channel中。
Master代碼
#!/usr/bin/env python# -*- coding: utf-8 -*-import timeimport threadingimport randomimport redisREDIS_HOST = 'localhost'REDIS_PORT = 6379REDIS_DB = 0CHANNEL_DISPATCH = 'CHANNEL_DISPATCH'CHANNEL_RESULT = 'CHANNEL_RESULT'class MyMaster():def __init__(self):passdef start(self):MyServerResultHandleThread().start()MyServerDispatchThread().start()class MyServerDispatchThread(threading.Thread):def __init__(self):threading.Thread.__init__(self)def run(self):r = redis.StrictRedis(host=REDIS_HOST, port=REDIS_PORT, db=REDIS_DB)for i in range(1, 100):channel = CHANNEL_DISPATCH + '_' + str(random.randint(1, 3))print("Dispatch job %s to %s" % (str(i), channel))ret = r.publish(channel, str(i))if ret == 0:print("Dispatch job %s failed." % str(i))time.sleep(5)class MyServerResultHandleThread(threading.Thread):def __init__(self):threading.Thread.__init__(self)def run(self):r = redis.StrictRedis(host=REDIS_HOST, port=REDIS_PORT, db=REDIS_DB)p = r.pubsub()p.subscribe(CHANNEL_RESULT)for message in p.listen():if message['type'] != 'message':continueprint("Received finished job %s" % message['data'])if __name__ == "__main__":MyMaster().start()time.sleep(10000)
說明
MyMaster類 - master主程式,用來啟動dispatch和resulthandler的線程
MyServerDispatchThread類 - 派發作業線程,產生作業並派發到計算節點
MyServerResultHandleThread類 - 作業運行結果處理線程,從channel裡擷取作業結果並顯示
Slave代碼
#!/usr/bin/env python# -*- coding: utf-8 -*-from datetime import datetimeimport timeimport threadingimport randomimport redisREDIS_HOST = 'localhost'REDIS_PORT = 6379REDIS_DB = 0CHANNEL_DISPATCH = 'CHANNEL_DISPATCH'CHANNEL_RESULT = 'CHANNEL_RESULT'class MySlave():def __init__(self):passdef start(self):for i in range(1, 4):MyJobWorkerThread(CHANNEL_DISPATCH + '_' + str(i)).start()class MyJobWorkerThread(threading.Thread):def __init__(self, channel):threading.Thread.__init__(self)self.channel = channeldef run(self):r = redis.StrictRedis(host=REDIS_HOST, port=REDIS_PORT, db=REDIS_DB)p = r.pubsub()p.subscribe(self.channel)for message in p.listen():if message['type'] != 'message':continueprint("%s: Received dispatched job %s " % (self.channel, message['data']))print("%s: Run dispatched job %s " % (self.channel, message['data']))time.sleep(2)print("%s: Send finished job %s " % (self.channel, message['data']))ret = r.publish(CHANNEL_RESULT, message['data'])if ret == 0:print("%s: Send finished job %s failed." % (self.channel, message['data']))if __name__ == "__main__":MySlave().start()time.sleep(10000)
說明
MySlave類 - slave節點主程式,用來啟動MyJobWorkerThread的線程
MyJobWorkerThread類 - 從channel裡擷取派發的作業並將運行結果發送回master
測試
首先運行MySlave來定義派發作業channel。
然後運行MyMaster派發作業並顯示執行結果。
有關Python使用Redis實現作業調度系統(超簡單),小編就給大家介紹這麼多,希望對大家有所協助!