簡體   English   中英

減輕來自並發消息傳遞系統的DB WRITE爭用

[英]Mitigating DB WRITE contention from concurrent messaging system

請注意:盡管我的問題特別涉及Camel(2.11.0)和ActiveMQ(5.8.0),但實際上是有關並發消息傳遞解決方案的正確設計的,非常有可能讓任何人通過任何強大的消息傳遞和/或答案來回答並發經驗。

我有一個駱駝路線,首先從ActiveMQ隊列( myQueue )中讀取消息,然后將它們發送到Bean( processorBean )進行處理:

<camelContext id="my-camel-context" xmlns="http://camel.apache.org/schema/spring">
    <endpoint id="myQueue" uri="myBroker01:queue:myQueue" />

    <route id="my-route">
        <from ref="myQueue" />
        <to uri="bean:processorBean?method=process" /> 
    </route>
</camelContext>

和:

public class ProcessorBean {
    public void process(Exchange exchange) {
        String messageJSON = (String)exchange.getIn().getBody();

        // Example: now messageID might be "12345"
        String messageID = parseJSON(messageJSON, "messageID");

        // Look up DB records based on this messageID.
        // The same messageID will *always* return the same list of widgets.
        List<Widget> widgets = dao.getWidgetsByMessageID(messageID);

        // Make updates to widgets.
        for(Widget widget : widgets) {
            widget.setFizz(true);
            widget.setBuzz("Yahtzee!!!");
        }

        // Persist all updates to the widget list.
        dao.updateAll(widgets);
    }
}

該bean使用消息的ID(字符串messageID字段)在數據庫中查找一堆記錄,對其進行更改,然后保存。 這也是非常重要的要注意的是,在郵件到達myQueue從我無法控制的外部進程。 換句話說,我無法阻止具有相同messageID值的消息(以下稱為“重復”或重復消息 )出現在線程上。 因此,此外部進程可以將1000條消息發送到myQueue ,其中20條消息的messageID=12345都可以。

目前,我只有1個Camel使用者配置為正在運行(因此它是“單線程”)。 因此,當重復出現時,目前沒有任何危害(除了可能的不必要的性能問題)。 每條消息一次處理一次,如果有20條具有相同messageID消息,那么,相同的DB記錄將一遍又一遍地得到相同的精確(不必要的)更新。 當然,這不利於性能,但不會創建“不良數據”,臟寫,我們的生產競爭條件等。

現在,我想在方程式中添加更多的Camel使用者線程,以便可能有10個使用者線程全部從myQueue讀取。

顯然,現在我們有可能在數據庫中進行WRITE爭用。 假設myQueue上有2條消息,並且都具有messageID=12345 一個Camel使用者線程讀取第一條消息,而另一個線程同時或大約同時讀取第二條消息。 每個線程將其消息路由到其自己的processorBean的副本/版本。 兩個processorBean實例大約在同一時間執行,使用messageID從數據庫中讀取相同的記錄,對它們在內存中執行相同的操作,然后調用dao.updateAll(...)將更改寫入相同的內容記錄,同時。 如果兩個線程同時更新相同的數據庫記錄,則將發生爭用。

另一個重要的注意事項是,在這種情況下(太長的背景信息),不能選擇更改數據庫(由另一個團隊控制)以實現諸如分片,樂觀鎖定等功能。

我的問題: 在這種情況下,可以在Java層上做些什么來減輕WRITE爭用? 必須從應用程序內部處理WRITE爭用。 有什么想法嗎?

您可以像這樣使用全局鎖

synchronized(ProcessorBean.class) {
    // Persist all updates to the widget list.
    dao.updateAll(widgets);
}

暫無
暫無

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

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