2017-08-11 54 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(); 
    } 

} 
相关问题