2017-08-11 53 views
0

我有一個簡單的用例。我有一個系統,對REST服務(有許多實例)的重複請求是不允許的。但是,由於複雜的數據存儲配置和下游服務也難以防止。我是否應該使用Hazelcast檢測重複請求到REST服務

所以我可以防止重複「交易」的唯一方法是有一個集中的地方,我寫一個請求數據的唯一散列。每個REST端點首先檢查新請求的散列是否已經存在,並且僅在沒有這種散列存在時纔會繼續。

爲了這個問題的目的,假設不可能用數據庫約束來做到這一點。

一個解決方案是在數據庫中創建一個表,用於存儲我的請求散列,並且在繼續處理請求之前始終寫入此表。但是,我想要比這更輕的東西。

另一種解決方案是使用類似Redis的東西,並在繼續處理請求之前寫入redis我的獨特散列。但是,我不想旋轉Redis集羣並維護它等等。我想在每個應用程序實例中嵌入Hazelcast,並在那裏寫入我獨特的哈希值。理論上,所有實例都會在內存網格中看到散列,並能夠檢測到重複的請求。這解決了我擁有比數據庫更輕的解決方案的問題,以及不需要維護Redis集羣的其他要求。

好吧,現在終於爲我的問題。這個用例使用Hazelcast是個好主意嗎? 榛樹會不會足夠快地檢測出重複的請求,而這些請求會以毫秒或微秒爲單位發生?

如果請求1進入實例1,請求2進入實例2微秒。實例1向hazelcast寫入請求的散列,實例2僅在毫秒後檢查哈希是否存在散列才能檢測到哈希值?榛色是否會及時在整個集羣中傳播數據?它甚至需要這樣做嗎?

在此先感謝,所有的想法都歡迎。

回答

1

對於這種用例,Hazelcast絕對是一個不錯的選擇。特別是如果您只使用Map<String, Boolean>並僅使用Map::containsKey進行測試,而不是檢索元素並檢查null。放置元素時還應該放置一個TTL,這樣就不會耗盡內存。但是,與Redis相同,我們建議將Hazelcast與獨立羣集一起用於「更大」的數據集,因爲緩存元素的生命週期通常會干擾應用程序的其餘部分,並使GC優化變得複雜。運行Hazelcast嵌入式應用程序只能在運行時對應用程序進行認真考慮和測試後才能使用。

+0

有道理。還有一個問題,那就是Hazelcast客戶端的.NET實現。但是,這是否意味着我只能從.NET加入現有的Hazelcast羣集,或者實際上是否可以將hazelcast實例嵌入.NET應用程序(類似於java)?意思是,我可以創建一個只包含.NET嵌入式hazelcast實例的新集羣嗎? – DKhanaf

+1

不,它只是一個客戶端,也就是說,集羣仍然是Java。 – noctarius

1

是的,您可以使用Hazelcast分佈式映射來檢測到對REST服務的重複請求,因爲每當在hazelcast中放置操作時,地圖數據將可用於所有其他集羣實例。

從我讀過的和在測試中看到的,它並沒有真正的複製。它使用數據網格將主要數據均勻地分佈到所有節點上,而不是每個節點都保留所有內容的完整副本並進行復制以同步數據。關於這一點的好處是沒有數據滯後,這是任何複製策略固有的。

存儲在另一個節點上的每個節點數據都有一個備份副本,這顯然取決於複製,但備份副本僅在節點崩潰時使用。

請參閱下面的代碼,它創建兩個hazelcast聚集實例並獲取分佈式映射。一個將數據放入IMap和其他實例的hazelcast實例正從IMap獲取數據。

import com.hazelcast.config.Config; 
import com.hazelcast.core.Hazelcast; 
import com.hazelcast.core.HazelcastInstance; 
import com.hazelcast.core.IMap; 

public class TestHazelcastDataReplication { 

    //Create 1st Instance 
    public static final HazelcastInstance instanceOne = Hazelcast 
      .newHazelcastInstance(new Config("distributedFisrtInstance")); 
    //Create 2nd Instance 
    public static final HazelcastInstance instanceTwo = Hazelcast 
      .newHazelcastInstance(new Config("distributedSecondInstance")); 
    //Insert in distributedMap using instance one 
    static IMap<Long, Long> distributedInsertMap = instanceOne.getMap("distributedMap"); 
    //Read from distributedMap using instance two 
    static IMap<Long, Long> distributedGetMap = instanceTwo.getMap("distributedMap"); 

    public static void main(String[] args) { 
     new Thread(new Runnable() { 
      @Override 
      public void run() { 
       for (long i = 0; i < 100000; i++) { 
        //Inserting data in distributedMap using 1st instance 
        distributedInsertMap.put(i, System.currentTimeMillis()); 
        //Reading data from distributedMap using 2nd instance 
        System.out.println(i + " : " + distributedGetMap.get(i)); 
       } 
      } 
     }).start(); 
    } 

} 
相關問題