【问题标题】:Should I use Hazelcast to detect duplicate requests to a REST service我应该使用 Hazelcast 检测对 REST 服务的重复请求吗
【发布时间】:2017-08-11 02:39:36
【问题描述】:

我有一个简单的用例。我有一个系统,其中不允许对 REST 服务(具有数十个实例)的重复请求。但是,由于复杂的数据存储配置和下游服务,也难以预防。

因此,我可以防止重复“事务”的唯一方法是有一个集中的地方,我可以在其中编写请求数据的唯一哈希。每个 REST 端点首先检查新请求的哈希是否已经存在,只有在不存在此类哈希时才会继续。

出于此问题的目的,假设无法使用数据库约束来执行此操作。

一种解决方案是在我存储请求哈希的数据库中创建一个表,并始终在继续请求之前写入该表。但是,我想要比这更轻的东西。

另一种解决方案是使用 Redis 之类的东西,并在继续请求之前将我的唯一哈希写入 redis。但是,我不想启动 Redis 集群并对其进行维护等。

我正在考虑将 Hazelcast 嵌入到我的每个应用程序实例中,并在那里写入我唯一的哈希值。理论上,所有实例都会看到内存网格中的哈希值,并且能够检测到重复请求。这解决了我的问题,即拥有比数据库更轻的解决方案以及不必维护 Redis 集群的其他要求。

现在终于可以回答我的问题了。在这个用例中使用 Hazelcast 是个好主意吗? hazelcast 是否足够快以检测以毫秒或微秒为间隔的重复请求?

如果请求 1 进入实例 1,请求 2 进入实例,则相隔 2 微秒。实例 1 将请求的哈希值写入 hazelcast,实例 2 仅在毫秒后检查 hazelcast 是否存在哈希值,是否会检测到哈希值? hazelcast 是否会及时在集群中传播数据?它甚至需要这样做吗?

提前致谢,欢迎所有想法。

【问题讨论】:

    标签: hazelcast


    【解决方案1】:

    Hazelcast 对于这种用例来说绝对是一个不错的选择。特别是如果您只使用Map<String, Boolean> 并使用Map::containsKey 进行测试,而不是检索元素并检查null。放元素的时候还应该放一个TTL,这样就不会耗尽内存。但是,与 Redis 一样,我们建议将 Hazelcast 与独立集群一起用于“更大”的数据集,因为缓存元素的生命周期通常会干扰应用程序的其余部分并使 GC 优化复杂化。只有在认真考虑并在运行时对应用程序进行测试后,才应选择运行嵌入式 Hazelcast。

    【讨论】:

    • 有道理。另一个问题是,Hazelcast 客户端有一个 .NET 实现。但是,这是否意味着我只能从 .NET 加入现有的 Hazelcast 集群,或者我实际上可以将 hazelcast 实例嵌入到 .NET 应用程序中(类似于 java)?意思是,我可以创建一个仅包含 .NET 嵌入式 hazelcast 实例的新集群吗?
    • 不,它只是一个客户端,也就是说,集群仍然是 Java。
    【解决方案2】:

    是的,您可以使用 Hazelcast 分布式地图来检测对 REST 服务的重复请求,因为只要在 hazelcast 地图中进行放置操作,所有其他集群实例都可以使用数据。

    根据我在测试中阅读和看到的内容,它实际上并没有复制。它使用数据网格将主要数据均匀地分布在所有节点上,而不是每个节点保留所有内容的完整副本并复制以同步数据。这样做的好处是没有数据延迟,这是任何复制策略所固有的。

    每个节点的数据都有一个备份副本存储在另一个节点上,这显然依赖于复制,但备份副本仅在节点崩溃时使用。

    请参阅以下代码,该代码创建两个 hazelcast 集群实例并获取分布式地图。一个 hazelcast 实例将数据放入分布式 IMap,另一个实例从 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();
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-29
      • 2019-02-02
      • 2020-02-16
      • 1970-01-01
      • 1970-01-01
      • 2017-07-19
      • 1970-01-01
      • 2018-02-23
      相关资源
      最近更新 更多