1. 程式人生 > >jedis超時重試機制註意事項

jedis超時重試機制註意事項

del number 十進制 包含 str 沒有 時間 機制 await

最近使用redis集群進行incr操作,總是發現計數不準確,後來經過檢查發現redis在執行incr超時會執行重試機制,造成計數不準確,測試代碼:

/**
     *  incrf:
     *  將 key 中儲存的數字值增一。
     如果 key 不存在,那麽 key 的值會先被初始化為 0 ,然後再執行 INCR 操作。
     如果值包含錯誤的類型,或字符串類型的值不能表示為數字,那麽返回一個錯誤。
     本操作的值限制在 64 位(bit)有符號數字表示之內。
     這是一個針對字符串的操作,因為 Redis 沒有專用的整數類型,所以 key 內儲存的字符串被解釋為十進制 64 位有符號整數來執行 INCR 操作。
     返回值:     執行 INCR 命令之後 key 的值。

     這裏有問題,最終數據結果大於10000 
     這是因為設置的超時時間太小了,他去重試了,所以最終結果大於10000
     */
    @Test
    public void incrTest() throws InterruptedException {
        /**
         * 測試線程安全
         */
        jedisCluster.del("incrNum");
        final AtomicInteger atomicInteger = new AtomicInteger(0);
        final CountDownLatch countDownLatch = new CountDownLatch(10);
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        for(int i = 0 ; i < 10 ; i ++){
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    //每個線程增加1000次,每次加1
                    for(int j = 0 ; j < 1000 ; j ++){
                        atomicInteger.incrementAndGet();
                        jedisCluster.incr("incrNum");
                    }

                    countDownLatch.countDown();
                }
            });
        }

        countDownLatch.await();
        System.out.println(jedisCluster.get("incrNum"));
        System.out.println(atomicInteger);
    }
這是個多線程的demo,不管多線程還是單線程,我最終得到的結果都是比10000大。這就奇怪了,incr
是原子的,理論上不應該會這樣。我起初以為是jedis客戶端的BUG,後來仔細一看才發現,這不是BUG,是我在創建jediscluster的時候設置的超時時間太短了,導致其超時重試。

解決辦法

將超時時間設置的大一些。

我們在使用這些開源框架的時候,一定要全面了解其運作原理,這樣才能事半功倍。另外需要註意,想httpclient、dubbo等RPC框架都會有超時重試機制,在使用的時候要註意。

jedis超時重試機制註意事項