spring-data-redis - redis并发计数
phpcn_u1582
phpcn_u1582 2017-04-25 09:03:18
0
2
1121

说明:
用redis计数器存取用户的操作次数,最多3次,但是并发会超过3次,下面的代码对吗?

BoundValueOperations<String, String> operations = redisTemplate.boundValueOps("key1");
        String key1 = operations.get();
        if (StringUtils.isEmpty(key1)) {
            service.do();//这里是业务逻辑操作成功之后,计数器加1
            operations.increment(1);
        } else {
            if (Integer.parseInt(key1) < 2) {
                service.do();//这里是业务逻辑操作成功之后,计数器加1
                operations.increment(1);
            }
        }
phpcn_u1582
phpcn_u1582

répondre à tous(2)
世界只因有你

Pour ce genre d'activité de comptage, vous devez d'abord compter, puis faire des affaires. Si l'affaire est terminée et que le compteur est supérieur à la valeur limite, vous serez abasourdi.

Mon plan est le suivant :
En raison d'une incohérence des données causée par la concurrence, vous pouvez envisager d'utiliser la commande INCR de Redis pour incrémenter de 1 et obtenir la dernière valeur (il s'agit d'une opération unique, elle n'entraînera donc pas incohérence) :

  • S'il est supérieur à 3, cela signifie qu'il a été dépassé et que c'est fini

  • Si
  • est inférieur ou égal à 3, exécutez à nouveau l'entreprise (vous pouvez également considérer le compteur d'annulation en cas d'échec d'exécution de l'entreprise).

左手右手慢动作

Il existe certains défauts dans l'implémentation des fonctions ci-dessus via le client Java. Dans le cas d'une concurrence élevée, les données peuvent être incohérentes. Il est recommandé d'utiliser le script lua pour encapsuler toute la logique afin de garantir l'atomicité de l'opération ; il peut être chargé via SCRIPT LOAD. Le script est mis en cache sur le serveur et exécuté via la valeur de contrôle sha1 + les paramètres (Key, ARG) pour réduire la transmission réseau

;

Donnez un exemple :
1. Exigences fonctionnelles : si la clé n'existe pas, définissez-la et renvoyez false, et définissez le délai d'attente et le nombre = 1 lorsque le délai d'attente est atteint ou que le nombre spécifié est atteint, return false et restart Définissez le timeout et count=1 si le timeout n'est pas atteint et que le nombre spécifié n'est pas atteint, return true et augmentez le count

Le script redis.lua est le suivant :

local key = KEYS[1];
local expire = tonumber(KEYS[2]);
local number = tonumber(KEYS[3]);
local count = tonumber(redis.call("GET",key));
if count == nil then
        redis.call("SETEX",KEYS[1],expire,"1");
        return false;
else
        if count +1 >= number then;
                redis.call("SETEX",KEYS[1],expire,"1");
                return false;
        else
                redis.call("INCR",KEYS[1]);
                return true;
        end
end

Le code java est le suivant :

   public static final String REDIS_LUA = "redis.call('select',1);local key = KEYS[1];local expire = tonumber(KEYS[2]);" +
            "local number = tonumber(KEYS[3]);local count = tonumber(redis.call('GET',key));" +
            "if count == nil then redis.call('SETEX',KEYS[1],expire,'1');return 0;" +
            "else if count +1 >= number then redis.call('SETEX',KEYS[1],expire,'1');return 0;" +
            "else redis.call('INCR',KEYS[1]);return 1;end;end;";
    
    private static final String redisScript;
    

    static {
        try {
            Conf.load();
        } catch (Exception e) {
            e.printStackTrace();
        }
        jedisPool = new JedisPool(Conf.getRedisHost(), Conf.getRedisPort());
        redisScript = loadLuaScript();
    }
   private static String loadLuaScript() {
        Jedis jedis = null;
        String redisScript = null;
        try {
            jedis = jedisPool.getResource();
            redisScript = jedis.scriptLoad(REDIS_LUA);
        } catch (Exception e) {
            if (jedis != null) {
                jedisPool.returnResource(jedis);
            }
        } finally {
            if (jedis != null) {
                jedisPool.returnResource(jedis);
            }
        }
        return redisScript;
    }
    
    
  
调用脚本
 Object result = jedis.evalsha(redisScript, ARGS_LENGTH
                    , key, expireTime, countVal);
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal