【问题标题】:Handling race conditions with Redis Cache使用 Redis 缓存处理竞争条件
【发布时间】:2022-01-05 15:01:51
【问题描述】:

我正在查看一个问题,其中我有一个包含字符串键和计数器的对象。每次访问对象时,计数器都会递减。这带来了竞争条件的问题。为了解决这个问题,我使用 synchronized 关键字编写了以下代码

try {
            option = cartRepository.findById(url);
            Rate rate = option.get();
            synchronized (this) {
                if(rate.getRate() > 0) {
                    rate.decRate(1);
                    allow = true;
                    cartRepository.save(rate);
                } 
            }
        } catch(NoSuchElementException e) {
            cartRepository.save(new Rate(url, 5));
            allow = true;
        } 

我想知道,redis 本身是否具有在您每次访问该键时递增或在这种情况下递减计数器的功能。 文档有点混乱。它确实谈到了键的自动增量。但我猜,它不是用钥匙和计数器创建一个两部分的钥匙。但是每次创建和保存新对象时都会自动增加一个键。

【问题讨论】:

  • 你可以使用INCRDECR redis 命令来更改计数器值吗?这些命令在执行操作后返回计数器值。如果您有许多计数器需要维护,您可以将它们存储在哈希图中并使用HINCRBY 命令。
  • 我查看了 INCR 和 DECR 的文档,非常混乱。它增加一个数字键。我的密钥都是 URL。而且我不知道如何使用该命令。我有一个非常简单的设置。我的代表扩展了 CrudRepository 。在我看来,我不必使用 CrudRepository 连接到 REDIS

标签: java redis race-condition


【解决方案1】:

你可以有一个键来保存计数器并使用INCR 命令来更改计数器值。该命令执行操作后返回计数器值。

您可以在 Spring Data Redis 中使用ValueOperations 来发出此命令。这是示例代码:

StringRedisTemplate rt = new StringRedisTemplate(factory);

ValueOperations<String, String> valueOps = rt.opsForValue();

valueOps.set(KEY, "10");
System.out.println(valueOps.get(key));
System.out.println(valueOps.increment(KEY, 1));
System.out.println(valueOps.increment(KEY, 1));
System.out.println(valueOps.increment(KEY, -1));

输出将是:

10
11
12
11

如果您有许多计数器需要维护,您可以将它们存储在hashmap 中并使用HINCRBY 命令。使用 Spring Data Redis,您可以使用 HashOperations 来操作散列中的值。 See this page获取更详细的解释。

【讨论】:

  • 谢谢你,这就是我要找的,干净简单,可行。
【解决方案2】:

感谢 Sergie,这是有效的代码

public boolean isAllowed(String url, String maxRate) {
        logger.info("URL is "+url);
        boolean allow = false;
        ValueOperations<String, String> valueOps = redisTemplate.opsForValue();
        String rate = valueOps.get(url);
        logger.info("RATE "+rate);
        if(rate == null) {
            valueOps.set(url, maxRate, 5, TimeUnit.SECONDS);
            allow = true;
        } else {
            valueOps.decrement(url, 1);
            if(Integer.parseInt(rate) > 0) {
                allow = true;
            }
        }
        return allow;
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-12
    • 2011-04-01
    相关资源
    最近更新 更多