incr、incrby、decr、decrby命令的作用和用法
redis中incr、incrby、decr、decrby屬於string數據結構,它們是原子性遞增或遞減操作。
- incr遞增1並返回遞增后的結果;
- incrby根據指定值做遞增或遞減操作並返回遞增或遞減后的結果(incrby遞增或遞減取決於傳入值的正負);
- decr遞減1並返回遞減后的結果;
- decrby根據指定值做遞增或遞減操作並返回遞增或遞減后的結果(decrby遞增或遞減取決於傳入值的正負);
設置incr:key和decr:key觀察用法和執行結果
1.首次觀察incr:key的值,可以看到沒有結果
127.0.0.1:6381> GET incr:key
127.0.0.1:6381>
2.對incr:key執行incr命令,可以看到redis返回了遞增后的結果1。incr命令會返回遞增后的結果
127.0.0.1:6381> incr incr:key 1 127.0.0.1:6381>
3.對incr:key執行incrby命令,能看到redis返回了遞增后的結果5。incrby命令會返回遞增后的結果
127.0.0.1:6381> incrby incr:key 4 5 127.0.0.1:6381>
4.對incr:key執行incrby命令,這次傳入一個負數,能觀察到redis返回了遞減后的結果2
127.0.0.1:6381> incrby incr:key -3 2 127.0.0.1:6381>
5.對incr:key執行incrby命令,同樣傳入負數, 可以觀察到incr:key經過遞減后結果變成了負數
127.0.0.1:6381> incrby incr:key -4 -2 127.0.0.1:6381>
6.首次觀察decr:key,沒有任何結果
127.0.0.1:6381> GET decr:key 127.0.0.1:6381>
7.對decr:key執行decr命令,可以看到redis返回了遞減后的結果
127.0.0.1:6381> decr decr:key -1 127.0.0.1:6381>
8.對decr:key執行decrby命令,可以看到redis返回了遞減后的結果,這里的值輸入的是4而不是-4
127.0.0.1:6381> decrby decr:key 4 -5 127.0.0.1:6381>
9.對decr:key執行decrby命令,這次輸入一個負數,觀察一下結果
127.0.0.1:6381> decrby decr:key -1 -4 127.0.0.1:6381>
並發遞增和遞減
做一個實驗,並發100個線程對同一個key做操作,其中50個執行incr命令,另外50個執行decr命令,觀察一下結果
/** * 並發100個線程,50個線程做decr命令,另外50個線程做incr命令 * * @author tianshu on 16/10/31 上午10:52. */ public class MultipleDecrIncr { /** decr線程數量 */ private static final int DECR_THREAD_COUNT = 50; /** incr線程數量 */ private static final int INCR_THREAD_COUNT = 50; private static CountDownLatch begin = new CountDownLatch(DECR_THREAD_COUNT + INCR_THREAD_COUNT); private static CountDownLatch finish = new CountDownLatch(DECR_THREAD_COUNT + INCR_THREAD_COUNT); static final String KEY = "string:decr:incr"; public static void main(String[] args) throws InterruptedException { for(int i = 0; i < DECR_THREAD_COUNT; ++i) { new DecrThread().start(); begin.countDown(); } for(int i = 0; i < INCR_THREAD_COUNT; ++i) { new IncrThread().start(); begin.countDown(); } finish.await(); JedisConnect jedisConnect = JedisConnect.getJedisConnect(); Jedis jedis = jedisConnect.getJedis(); String value = jedis.get(KEY); System.out.println(value); jedisConnect.releaseJedis(jedis); } /** * decr命令線程 */ static class DecrThread extends Thread { @Override public void run() { try { begin.await(); } catch (InterruptedException e) { e.printStackTrace(); } JedisConnect jedisConnect = JedisConnect.getJedisConnect(); Jedis jedis = jedisConnect.getJedis(); jedis.decr(KEY); jedisConnect.releaseJedis(jedis); finish.countDown(); } } /** * incr命令線程 */ static class IncrThread extends Thread { @Override public void run() { try { begin.await(); } catch (InterruptedException e) { e.printStackTrace(); } JedisConnect jedisConnect = JedisConnect.getJedisConnect(); Jedis jedis = jedisConnect.getJedis(); jedis.incr(KEY); jedisConnect.releaseJedis(jedis); finish.countDown(); } } }
應用場景
個人覺得這類命令一般會應用到計數器場景
- 單號生成:根據業務生成key,每當需要單號時可以使用incr獲得一個新的序列號。
- 錯誤攔截:比如有的網站賬號密碼輸入錯誤N次之后,會做一些特殊處理;使用incr是實現這種功能的方式之一,可以根據用戶的特殊標識表示key,每當賬號密碼輸錯時使用incr命令做遞增。
- 非法攔截:某段時間限制同IP請求同一接口次數