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

说明:
用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

membalas semua(2)
世界只因有你

Untuk perniagaan mengira seperti ini, anda perlu mengira dahulu dan kemudian baru berniaga. Jika perniagaan telah selesai dan kaunter didapati lebih besar daripada nilai had, anda akan terkejut.

Pelan saya ialah:
Disebabkan ketidakkonsistenan data yang disebabkan oleh konkurensi, anda boleh mempertimbangkan untuk menggunakan perintah INCR Redis untuk menambahnya sebanyak 1 dan mendapatkan nilai terkini (ini adalah operasi sekali sahaja, jadi ia tidak akan menyebabkan tidak konsisten):

  • Jika lebih daripada 3, bermakna ia telah melebihi dan sudah tamat; Jika

  • kurang daripada atau bersamaan dengan 3, laksanakan perniagaan sekali lagi (anda juga boleh mempertimbangkan kaunter balik untuk kegagalan pelaksanaan perniagaan).
左手右手慢动作

Terdapat kelemahan tertentu dalam melaksanakan fungsi di atas melalui klien Java Dalam kes konkurensi tinggi, data mungkin tidak konsisten Adalah disyorkan untuk menggunakan skrip lua untuk merangkumkan keseluruhan logik untuk memastikan keatoman operasi. Anda boleh menggunakan SCRIPT LOAD ke Skrip dicache ke pelayan dan dilaksanakan melalui nilai semakan sha1 + parameter (Kunci, ARG) untuk mengurangkan penghantaran rangkaian

Beri anda contoh:
1 Keperluan fungsian: Jika kunci tidak wujud, tetapkannya dan kembalikan palsu, dan tetapkan tamat masa dan kiraan = 1 apabila tamat masa telah dicapai atau kiraan yang ditentukan tercapai, return false dan mulakan semula Tetapkan tamat masa dan kiraan=1; jika tamat masa tidak tercapai & kiraan yang ditentukan tidak tercapai, kembalikan benar dan kiraan incr

Skrip redis.lua adalah seperti berikut:

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

Kod java adalah seperti berikut:

   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);
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan