Caffeine批量加載淺析

最近項目中的本地緩存,看是從Guava改爲了Caffeine,聽說是性能更好,既然性能更好的話,那麼就用起來吧。不過在使用過程當中,發現了單個load和批量loadall方面的一些小設置,記錄一下。css

通常說來,咱們獲取單條記錄的時候,通常都是 cache.get(id),當數據過時,會從提早設定好的load方法中獲取數據。html

一樣的,若是咱們想批量獲取記錄的時候,通常都是用cache.getAll(ids),當數據過去,會從提早設定好的loadAll方法中獲取數據。redis

實際在測試的時候,發現,利用以下的緩存初始化方式,不管怎麼泡cache.getAll(ids)方法,發現總會從load方法中加載數據,硬生生的把批量獲取變成了單個循環獲取,這就致使幾十個redis命令一塊兒發到redis集羣那邊,形成了網絡浪費和性能差別:緩存

 batchNumCache = Caffeine.newBuilder()
                .initialCapacity(cacheSize)
                .maximumSize(cacheSize)
                .refreshAfterWrite(cacheTime, TimeUnit.SECONDS)
                .build(new CacheLoader<Long, Map<String, Integer>>() {

                    @Override
                    public Map<String, Integer> load(Long batchId) throws Exception {
                        return getBatchNumJimdb(batchId);
                    }

                    @Override
                    public Map<Long, Map<String, Integer>> loadAll(Iterable<? extends Long> batchIds) throws Exception {
                        if (Iterables.isEmpty(batchIds)) {
                            return null;
                        }
                        return getAllBatchNumJimdb(Lists.newArrayList(batchIds));
                    }
                });

如上代碼能夠看出,load方法會調用getBatchNumJimdb加載數據,而loadAll方法會調用getAllBatchNumJimdb加載數據,getAllBatchNumJimdb加載數據的方式就是利用redis的pipeline,一次性將請求發給redis,而後獲取返回結果。網絡

雖然如上代碼不能按照咱們既定的方式工做,那麼確定配置有些什麼問題,後來通過諸多的ut測試,發現設置上expireAfterWrite屬性,總體就完美了。最終代碼以下:ide

 

batchNumCache = Caffeine.newBuilder()
                .initialCapacity(cacheSize)
                .maximumSize(cacheSize)
                .refreshAfterWrite(cacheTime, TimeUnit.SECONDS)
                .expireAfterWrite(cacheTime, TimeUnit.SECONDS)
                .build(new CacheLoader<Long, Map<String, Integer>>() {

                    @Override
                    public Map<String, Integer> load(Long batchId) throws Exception {
                        return getBatchNumJimdb(batchId);
                    }

                    @Override
                    public Map<Long, Map<String, Integer>> loadAll(Iterable<? extends Long> batchIds) throws Exception {
                        if (Iterables.isEmpty(batchIds)) {
                            return null;
                        }
                        return getAllBatchNumJimdb(Lists.newArrayList(batchIds));
                    }
                });

如上代碼,總體就ok了。當使用cache.get的時候,會從load加載,當使用cache.getall的時候,會從loadall加載。性能

相關文章
相關標籤/搜索