redisはwatch、multi、execコマンドに有利で、秒殺機能を実現する
5348 ワード
1、注意点:redis watchコマンドは、1つ(または複数)のkeyを監視するために使用され、トランザクションが実行される前にこの(またはこれら)keyが他のコマンドによって変更されると、トランザクションが中断されます.モニタはEXECコマンドまで継続します(トランザクションのコマンドはEXEC以降に実行されるため、MULTIコマンドの後でWATCHモニタのキー値を変更できます)
2:コードは次のとおりです.
2:コードは次のとおりです.
public class JedisRunnable implements Runnable {
private Jedis jedis = JedisUtil.getJedis();
private String userId;
public JedisRunnable(String userId) {
this.userId = userId;
}
public void run() {
try {
// , key , OK, 。
jedis.watch(RedisSecKiller.WATCH_KEY);
//
int leftGoodsNum = Integer.valueOf(jedis.get(RedisSecKiller.WATCH_KEY));
// 0 , 1 。
if (leftGoodsNum > 0) {
// jedis
Transaction tx = jedis.multi();
// : Goods 1 , tx.exec() Goods 。
tx.decrBy(RedisSecKiller.WATCH_KEY, 1);
// : Goods 1, tx.exec() "OK"。
// tx.set(RedisSecKiller.WATCH_KEY, String.valueOf(leftGoodsNum - 1));
// , 。
List
public class RedisSecKiller {
//
private static final int N_THREADS = 5;
// jedis watch WATCH_KEY, , 。
public static final String WATCH_KEY = "Goods";
//
private static final int GOODS_NUM = 1000;
//
private static final int USER_NUM = 100;
public static void main(String[] args) {
// , N_THREADS 。
ExecutorService executorService = Executors.newFixedThreadPool(N_THREADS);
Jedis jedis = JedisUtil.getJedis();
// 10
jedis.set(WATCH_KEY, String.valueOf(GOODS_NUM));
jedis.close();
// USER_NUM
for (int i = 0; i < USER_NUM; i++) {
executorService.execute(new JedisRunnable(UUID.randomUUID().toString()));
// System.out.println("============== ===============");
}
executorService.shutdown();
}
}
public class JedisUtil {
private static final String ADDR = "192.168.222.130";
private static final int PORT = 6379;
private static final boolean TEST_ON_BORROW = true;
private static final int MAX_IDLE = 200;
private static JedisPool jedisPool = null;
static {
try {
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxIdle(MAX_IDLE);
config.setTestOnBorrow(TEST_ON_BORROW);
jedisPool = new JedisPool(config, ADDR, PORT);
} catch (Exception ex) {
ex.printStackTrace();
}
}
public synchronized static Jedis getJedis() {
try {
if (jedisPool != null) {
Jedis resource = jedisPool.getResource();
return resource;
}
return null;
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static void returnResource(final Jedis jedis) {
if (jedis != null) {
jedis.close();
}
}
}