Rumah > Soal Jawab > teks badan
说明:
用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);
}
}
世界只因有你2017-04-25 09:05:18
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
ringa_lee2017-04-25 09:05:18
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);