SpringBoot中RedisTemplate的MGET性能測試及解決辦法


項目中遇到了MGET獲取10000+數據時超時的問題,然后找到網友的測試結果如下(這里就不再重發測試代碼,測試結果一致)

結論

  • 一次操作10個key的性能達到一次操作1個key的88%
  • 一次操作20個key的性能達到一次操作1個key的72%
  • 一次操作50個key的性能達到一次操作1個key的59%
  • 一次操作60個key的性能達到一次操作1個key的53%
  • 一次操作80個key的性能達到一次操作1個key的43%
  • 一次操作100個key的性能大道一次操作1個key的41%
  • 一次操作200個key的性能只能達到一次操作1個key的25%,大約是一次處理100個key的60%
  • 一次操作500個key的性能只能達到一次操作1個key的11%,大約是一次處理100個key的28%
  • 一次操作800個key的性能只能達到一次操作1個key的7%,大約是一次處理100個key的17%
  • 當key數目在10以內時,mget性能下降趨勢非常小,性能基本上能達到redis實例的極限
  • 當key數目在10~100之間時,mget性能下降明顯,需要考慮redis性能衰減對系統吞吐的影響
  • 當key數目在100以上時,mget性能下降幅度趨緩,此時redis性能已經較差,不建議使用在OLTP系統中,或者需要考慮其他手段來提升性能。

解決辦法及測試結果(上代碼看結果)

 

package cn.hs;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.util.HashSet;
import java.util.Set;

@RunWith(SpringRunner.class)
@SpringBootTest
public class RedisGetTests {
    private static final String TYPE_NAME = RedisGetTests.class.getTypeName();

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Test
    public void contextLoads() {
        Set<String> keySet = new HashSet<>();
        for (int i = 0; i < 100000; i++) {
            String key = TYPE_NAME + ":" + i;
            keySet.add(key);
        }

        long time = System.currentTimeMillis();
        multiGet(keySet);
        System.out.println("redisTemplate.opsForValue().multiGet \t 耗時:" + (System.currentTimeMillis() - time));

//        排除,太慢了
//        time = System.currentTimeMillis();
//        getData(keySet);
//        System.out.println("redisTemplate.opsForValue().get \t\t 耗時:" + (System.currentTimeMillis() - time));
// 推薦 time = System.currentTimeMillis(); getDataByPipelined(keySet); System.out.println("redisTemplate.executePipelined \t\t\t 耗時:" + (System.currentTimeMillis() - time));
    }

    private void multiGet(Set<String> keySet) {
        redisTemplate.opsForValue().multiGet(keySet);
    }

    private void getData(Set<String> keySet) {
        for (String key : keySet) {
            redisTemplate.opsForValue().get(key);
        }
    }

    private void getDataByPipelined(Set<String> keySet) {
        redisTemplate.executePipelined((RedisCallback<Object>) redisConnection -> {
            for (String key : keySet) {
                redisConnection.get(key.getBytes(StandardCharsets.UTF_8));
            }
            return null;
        });
    }

}

輸出結果

redisTemplate.opsForValue().multiGet      耗時:422
redisTemplate.executePipelined            耗時:177

 

推薦方式

    private void getDataByPipelined(Set<String> keySet) {
        redisTemplate.executePipelined((RedisCallback<Object>) redisConnection -> {
            for (String key : keySet) {
                redisConnection.get(key.getBytes(StandardCharsets.UTF_8));
            }
            return null;
        });
    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM