簡體   English   中英

Python / Redis中的任務委托

[英]Task delegation in Python/Redis

我在考慮可以解決以下問題的體系結構時遇到問題:

我有一個Web應用程序(生產者),可應要求接收一些數據。 我也有許多應處理此數據的過程(消費者)。 1個請求生成1批數據,並且只能由1個使用者處理。

我當前的解決方案包括接收數據,使用Redis將其緩存在內存中,通過消息通道發送一條消息,即消費者在同一通道上偵聽時已寫入數據,然后由消費者處理數據。 這里的問題是, 我需要阻止多個使用者使用相同的數據 那么,如何通知其他消費者我已經開始執行此任務?

生產者代碼(燒瓶端點):

    data = request.get_json()
    db = redis.Redis(connection_pool=pool)
    db.set(data["externalId"], data)
    # Subscribe to the batches channel and publish the id
    db.pubsub()
    db.publish('batches', request_key)
    results = None
    result_key = str(data["externalId"])

    # Wait till the batch is processed
    while results is None:
        results = db.get(result_key)
        if results is not None:
            results = results.decode('utf8')

    db.delete(data["externalId"])
    db.delete(result_key)

消費者:

    db = redis.Redis(connection_pool = pool)
    channel = db.pubsub()
    channel.subscribe('batches')

    while True:
        try:
            message = channel.get_message()
            message_data = bytes(message['data']).decode('utf8')
            external_id = message_data.split('-')[-1]
            data = json.loads(db.get(external_id).decode('utf8'))
            result = DataProcessor.process(data)
            db.set(str(external_id), result)
        except Exception:
            pass

正是由於這個原因,PUBSUB通常在任務排隊中存在問題。 從文檔( https://redis.io/topics/pubsub ):

SUBSCRIBE,UNSUBSCRIBE和PUBLISH實施“發布/訂閱”消息傳遞范例,其中(引用Wikipedia)發件人(發布者)未編程為將其消息發送給特定的接收者(訂戶)。 而是,將發布的消息定性為渠道,而不知道可能有哪些(如果有)訂戶。

可以考慮使用的一種流行替代方法是通過將元素推送到Redis列表的末尾來實現“發布”,並通過讓您的工作人員按一定的時間間隔輪詢該列表來實現“訂閱”(指數退避通常是一個適當的選擇)。 為了避免多個工作人員獲得同一工作的情況,請使用lpop獲取並從列表中刪除一個元素。 Redis是單線程的,因此可以確保每個工人只有一個工人。

因此,在發布方面,目標是這樣的:

db = redis.Redis(connection_pool=pool)
db.rpush("my_queue", task_payload)

在訂閱方面,您可以根據需要安全地並行運行這樣的循環:

while True:
    db = redis.Redis(connection_pool=pool)
    payload = db.lpop("my_queue")
    if not payload:
        continue
    < deserialize and process payload here >

請注意,這是因為我們推到右側后進先出隊列(LIFO) rpush和突然離開留下lpop 您可以通過組合lpush / lpop來輕松實現FIFO版本。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM