Springboot2.x 集成 jedis和spring-boot-starter-data-redis的性能测试比较(Jedis完胜:附带源码)

文章系转载,方便整理和归纳

版权声明:本文为CSDN博主「斌哥谈编程」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/houpeibin2012/article/details/105839651

1.pom文件引入jedis和spring-boot-starter-data-redis的依赖
2.其他依赖的引入(Swagger)
3.Jedis配置类
4.Jedis及spring-boot-starter-data-redis的配置信息
5.Swagger配置类
6.编写测试相关类
7.测试
7.1插入数据测试
7.2读取数据测试
7.3多线程读取数据测试
8. 结论

温馨提示:
本文配套代码:https://gitee.com/guduwuhen/springboot2-lesson/tree/master/redispro

1.pom文件引入jedis和spring-boot-starter-data-redis的依赖

<properties>
    <java.version>1.8</java.version>
    <jedis.version>2.9.0</jedis.version>
    <fastjson.version>1.2.68</fastjson.version>
    <guava.version>28.2-jre</guava.version>
</properties>
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>${jedis.version}</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

Springboot 使用的是2.2.4.RELEASE版本。

2.其他依赖的引入(Swagger)

如下是完整的pom文件代码:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.ieslab.powergrid</groupId>
    <artifactId>redispro</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demosvr</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <jedis.version>2.9.0</jedis.version>
        <fastjson.version>1.2.68</fastjson.version>
        <guava.version>28.2-jre</guava.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>${jedis.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>${guava.version}</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>${fastjson.version}</version>
        </dependency>


        <!-- 热部署时使用 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>
        <!-- set/get方法免写,需要安装idea的插件 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <!--单元测试-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>

        </dependency>
        <dependency>
            <groupId>org.junit.platform</groupId>
            <artifactId>junit-platform-launcher</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

3.Jedis配置类

RedisConfiguration.java

package com.test.redis.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

/** <p>Title: RedisConfiguration </p>
 * <p>Description: 用户rest接口类,测试demo使用</p>
 *
 * @author binge
 * @date 2020-2-20 下午7:15:30
 * @version V1.0
 */
@Configuration
public class RedisConfiguration {

    @Bean(name= "jedis.pool")
    @Autowired
    public JedisPool jedisPool(@Qualifier("jedis.pool.config") JedisPoolConfig config,
                               @Value("${jedis.pool.host}")String host,
                               @Value("${jedis.pool.port}")int port) {
        return new JedisPool(config, host, port);
    }

    @Bean(name= "jedis.pool.config")
    public JedisPoolConfig jedisPoolConfig (@Value("${jedis.pool.config.maxTotal}")int maxTotal,
                                            @Value("${jedis.pool.config.maxIdle}")int maxIdle,
                                            @Value("${jedis.pool.config.maxWaitMillis}")int maxWaitMillis) {
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(maxTotal);
        config.setMaxIdle(maxIdle);
        config.setMaxWaitMillis(maxWaitMillis);
        return config;
    }
}

4. Jedis及spring-boot-starter-data-redis的配置信息

spring:
  redis:
    #数据库索引
    database: 0
    host: 192.168.22.150
    port: 6379
    lettuce:
      pool:
        #最大连接数
        max-active: 100
        #最大阻塞等待时间(负数表示没限制)
        max-wait: 5000
        #最大空闲
        max-idle: 500
        #最小空闲
        min-idle: 8
    #连接超时时间
    timeout: 10000

jedis :
  pool :
    host : 192.168.22.150
    port : 6379
    config :
      maxTotal: 1000
      maxIdle: 1000
      maxWaitMillis : 100000

5. Swagger配置类

package com.test.redis.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

/** <p>Title: SwaggerConfig </p>
 * <p>Description: Swagger配置类</p>
 *
 * @author binge
 * @date 2020-2-20 下午7:15:30
 * @version V1.0
 */

@Configuration
@EnableSwagger2
public class SwaggerConfig {
    @Bean
    public Docket creatApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())   // 指定构建api文档的详细信息的方法,下面会有实现:apiInfo()
                .select()
                // 指定要生成api接口的包路径,这里把controller作为包路径,生成controller中的所有接口
                .apis(RequestHandlerSelectors.basePackage("com.test.redis.controller"))
                .paths(PathSelectors.any())
                .build();
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("Spring Boot集成Swagger2接口测试")
                .description("生成的接口如下")
                .version("1.0")
                .contact(new Contact("斌哥","https://blog.csdn.net/houpeibin2012","houpeibin@126.com"))
                .build();
    }
}

6. 编写测试相关类

TestController.java

package com.test.redis.controller;

import com.test.redis.entity.Result;
import com.test.redis.entity.TestDataEntity;
import com.test.redis.service.TestAsyncService;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.StringRedisConnection;
import org.springframework.data.redis.core.*;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.Pipeline;
import redis.clients.jedis.Response;
import java.util.*;
import java.util.Map.Entry;

/** <p>Title: TestController </p>
 * <p>Description: 测试redis</p>
 *
 * @author binge
 * @date 2020-2-20 下午7:15:30
 * @version V1.0
 */
@RestController
@Slf4j
@Api(tags="redis性能测试")
public class TestController {
    @Autowired
    private JedisPool jedisPool;
    @Autowired
    StringRedisTemplate redisTemplate;
    @Autowired
    TestAsyncService testAsyncService;


    @RequestMapping("del")
    @ApiOperation(value="删除所有库",notes="删除所有库")
    public Result del(){
        long startTime = System.currentTimeMillis();
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            jedis.flushAll();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //返还到连接池
            jedis.close();
        }
        return Result.ok(System.currentTimeMillis() - startTime);
    }

    @RequestMapping("insertStringData")
    @ApiOperation(value="单个String数据插入",notes="单个String数据插入")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "num", value = "插入条数", required = true, dataType = "Int", paramType="query"),
            @ApiImplicitParam(name = "type", value = "数据类型", required = true, dataType = "String", paramType="query")
    })
    public Result insertStringData(int num, String type){
        long startTime = System.currentTimeMillis();
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            for(int i=0; i<num; i++){
                jedis.set(TestDataEntity.getKey(i, type), TestDataEntity.getTestStringData(type));
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //返还到连接池
            jedis.close();
        }
        return Result.ok(System.currentTimeMillis() - startTime);
    }

    @RequestMapping("insertStringDataPipelined")
    @ApiOperation(value="jedis方式批量插入String数据",notes="jedis方式批量插入String数据")
    public Result insertStringDataPipelined(@ApiParam(name="num",value="插入条数",required = true)@RequestParam int num,
                                            @ApiParam(name="type",value="数据类型",required = true)@RequestParam String type){
        long startTime = System.currentTimeMillis();
        Jedis jedis = null;
        try {
            //使用管道方式,性能比单次获取性能高
            jedis = jedisPool.getResource();
            Pipeline pipeline = jedis.pipelined();
            Map<String, Response<String>> map = new HashMap<>();
            for(int i=0; i<num; i++){
                Response<String> sResponse= pipeline.set(TestDataEntity.getKey(i, type),TestDataEntity.getTestStringData(type));
                map.put(String.valueOf(i), sResponse);
            }
            pipeline.sync();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //返还到连接池
            jedis.close();
        }
        return Result.ok(System.currentTimeMillis() - startTime);
    }

    @RequestMapping("insertStringDataPipelinedByRedisTemplate")
    @ApiOperation(value="redisTemplate方式批量插入String数据",notes="redisTemplate方式批量插入String数据")
    public Result insertStringDataPipelinedByRedisTemplate(@ApiParam(name="num",value="插入条数",required = true)@RequestParam int num,
                                                          @ApiParam(name="type",value="数据类型",required = true)@RequestParam String type) {
        long startTime = System.currentTimeMillis();
        /* 插入多条数据 */
        redisTemplate.executePipelined(new SessionCallback<Object>() {
            @Override
            public <K, V> Object execute(RedisOperations<K, V> redisOperations) throws DataAccessException {
                for(int i=0;i<num;i++){
                    redisTemplate.opsForValue().set(TestDataEntity.getKey(i, type),TestDataEntity.getTestStringData(type));
                }
                return null;
            }
        });
        return Result.ok(System.currentTimeMillis() - startTime);
    }

    @RequestMapping("getDataByKey")
    @ApiOperation(value="根据key关键字获取所有key",notes="根据key关键字获取所有key")
    public Result getDataByKey(@ApiParam(name="key",value="key关键字",required = true)@RequestParam String key){
        long startTime = System.currentTimeMillis();
        Jedis jedis = null;
        Set<String> keys;
        try {
            jedis = jedisPool.getResource();
            keys = jedis.keys(key);
            log.info(".......keys:" + keys.size());
        } finally {
            //返还到连接池
            jedis.close();
        }
        return Result.ok((System.currentTimeMillis() - startTime) + ":数据个数:" + keys.size());
    }

    @RequestMapping("getValueBykey")
    @ApiOperation(value="根据key过滤获取数据",notes="根据key过滤获取数据")
    public Result getValueBykey(@ApiParam(name="key",value="过滤条件",required = true)@RequestParam String key){
        long startTime = System.currentTimeMillis();
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            //使用管道方式,性能比单次获取性能高
            Map<String, String> map = new HashMap<>();
            Set<String> keys = jedis.keys(key);

            for(String ketTmp :keys){
                try {
                    String sResponse= jedis.get(ketTmp);
                    map.put(ketTmp,sResponse);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            long haoshi = System.currentTimeMillis() - startTime;
            System.out.println("个数:" + map.size() + ";耗时:" + haoshi+ ";大小:" +  map.toString().getBytes().length/1024);
        } finally {
            //返还到连接池
            jedis.close();
        }
        return Result.ok(System.currentTimeMillis() - startTime);
    }



    @RequestMapping("getDataByPipelined")
    @ApiOperation(value="根据num,type过滤获取数据",notes="根据num,type过滤获取数据")
    public Result getDataByPipelined(@ApiParam(name="num",value="查询条数",required = true)@RequestParam int num,
                            @ApiParam(name="type",value="数据类型",required = true)@RequestParam String type){
        long startTime = System.currentTimeMillis();
        Jedis jedis = null;
        Map<String, Response<String>> map = null;
        try {
            jedis = jedisPool.getResource();
            //使用管道方式,性能比单次获取性能高
            Pipeline pipeline = jedis.pipelined();
            map = new HashMap<>();
            for(int i=0;i<num;i++){
                try {
                    Response<String> sResponse= pipeline.get(TestDataEntity.getKey(i, type));
                    map.put(String.valueOf(i), sResponse);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            pipeline.sync();
            int i = num-10;
            for (Entry<String, Response<String>> entry : map.entrySet()) {
                Response<String> sResponse=(Response<String>)entry.getValue();
                if(i<num){
                    System.out.println(entry.getKey()+"-----" + sResponse.get());
                }
                ++i;
            }
            System.out.println(map.size() + ":" + map.toString().getBytes().length/1024);
        } finally {
            //返还到连接池
            jedis.close();
        }
        return Result.ok((System.currentTimeMillis() - startTime) + ":数据个数:" + map.size() + ":" + map.toString().getBytes().length/1024);
    }

    @RequestMapping("getDataByPipelinedAndPipelineKey")
    @ApiOperation(value="根据key过滤获取数据",notes="根据key过滤获取数据")
    public Result getDataByPipelinedAndPipelineKey(@ApiParam(name="key",value="过滤条件",required = true)@RequestParam String key){
        long startTime = System.currentTimeMillis();
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            //使用管道方式,性能比单次获取性能高
            Pipeline pipeline = jedis.pipelined();
            Map<String, Response<String>> map = new HashMap<>();
            Response<Set<String>> keys = pipeline.keys(key);
            pipeline.sync();
            Set<String> sets = keys.get();
            for(String ketTmp :sets){
                try {
                    Response<String> sResponse= pipeline.get(ketTmp);
                    map.put(ketTmp,sResponse);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            pipeline.sync();
            long haoshi = System.currentTimeMillis() - startTime;
            System.out.println("个数:" + map.size() + ";耗时:" + haoshi+ ";大小:" +  map.toString().getBytes().length/1024);
        } finally {
            //返还到连接池
            jedis.close();
        }
        return Result.ok(System.currentTimeMillis() - startTime);
    }
    @RequestMapping("getDataByPipelinedAndJedisKey")
    @ApiOperation(value="根据key过滤获取数据",notes="根据key过滤获取数据")
    public Result getDataByPipelinedAndJedisKey(@ApiParam(name="key",value="过滤条件",required = true)@RequestParam String key){
        long startTime = System.currentTimeMillis();
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            //使用管道方式,性能比单次获取性能高
            Pipeline pipeline = jedis.pipelined();
            Map<String, Response<String>> map = new HashMap<>();
            Set<String> sets = jedisPool.getResource().keys(key);
            for(String ketTmp :sets){
                try {
                    Response<String> sResponse= pipeline.get(ketTmp);
                    map.put(ketTmp,sResponse);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            pipeline.sync();
            int i = sets.size()-10;
            for (Entry<String, Response<String>> entry : map.entrySet()) {
                Response<String> sResponse=(Response<String>)entry.getValue();
                if(i<sets.size()){
                    System.out.println(entry.getKey()+"-----" + sResponse.get());
                }
                ++i;
            }
            System.out.println(map.size() + ":" + map.toString().getBytes().length/1024);
        } finally {
            //返还到连接池
            jedis.close();
        }
        return Result.ok(System.currentTimeMillis() - startTime);
    }

    @RequestMapping("getDataByPipelinedByRedisTemplate")
    @ApiOperation(value="RedisTemplate根据key过滤获取数据",notes="RedisTemplate根据key过滤获取数据")
    public Result getDataByPipelinedByRedisTemplate(@ApiParam(name="key",value="过滤条件",required = true)@RequestParam String key){
        long startTime = System.currentTimeMillis();
        try {
            Set<String> sets = jedisPool.getResource().keys(key);
            List<String> keyList = new ArrayList<>();
            for(String ketTmp :sets){
                keyList.add(ketTmp);
            }
            List<Object> obj = redisTemplate.executePipelined((RedisCallback<String>) redisConnection -> {
                StringRedisConnection stringRedisConnection = (StringRedisConnection) redisConnection;
                for (String keyTmp : keyList) {
                    stringRedisConnection.get(keyTmp);
                }
                return null;
            });
            System.out.println(obj.size() + ":" + obj.toString().getBytes().length/1024);

        } finally {
            //返还到连接池
        }
        return Result.ok(System.currentTimeMillis() - startTime);
    }

    @RequestMapping("startAsyn")
    @ApiOperation(value="启动异步线程并发获取数据",notes="启动异步线程并发获取数据")
    public Result startAsyn(@ApiParam(name="num",value="线程个数",required = true)@RequestParam int num,
                            @ApiParam(name="key",value="过滤条件",required = true)@RequestParam String key){
        long startTime = System.currentTimeMillis();
        for (int i=0; i<num; ++i){
            testAsyncService.startAsyn(key);
        }
        return Result.ok(System.currentTimeMillis() - startTime);
    }

}

Result.java 返回结构

package com.test.redis.entity;

/** <p>Title: PersonService </p>
 * <p>Description: 通用Rest请求返回结构 </p>
 *
 * @author bingge
 * @date 2020-2-20 下午7:15:30
 * @version V1.0
 */
public class Result {
    //服务器返回的状态码(主要给程序员看)。例如 : 200 : 请求成功, 500 : 服务器内部错误,400 : 未知错误
    private Integer code;

    //返回码 1:成功  10000:系统错误 10001:参数错误  ...
    private Integer status;

    // 服务器的错误信息 ,主要返回给用户看
    private String msg;

    // 服务器返回的数据
    private Object data;

    public Result() {
    }

    //返回操作成功
    public static Result ok() {
        return ok(null);
    }

    //返回操作成功
    public static Result ok(Object data) {
        Result result = new Result();
        result.setCode(200);
        result.setStatus(1);
        result.setMsg("请求成功");
        result.setData(data);
        return result;
    }

    //返回操作成功
    public static Result error() {
        return error("请求失败");
    }

    //返回操作成功
    public static Result error(Integer code, Integer status, String msg) {
        Result result = new Result();
        result.setCode(code);
        result.setStatus(status);
        result.setMsg(msg);
        return result;
    }

    //返回操作成功
    public static Result error(String msg) {
        return error(500,0, msg);
    }

    //返回操作成功
    public static Result error(ErrorStatus errorStatus) {
        return error(500,errorStatus.value(), errorStatus.getMessage());
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public Integer getStatus() {
        return status;
    }

    public void setStatus(Integer status) {
        this.status = status;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }
}

全局异常捕捉处理GlobleExceptionHandler.java

package com.test.redis.utils;

import com.test.redis.entity.MyException;
import com.test.redis.entity.Result;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

/** <p>Title: GlobleExceptionHandler </p>
 * <p>Description: 全局异常捕捉处理</p>
 *
 * @author binge
 * @date 2020-2-20 下午7:15:30
 * @version V1.0
 */
@ControllerAdvice
public class GlobleExceptionHandler {

    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    public Result errorHandler(Exception ex) {
        //判断异常的类型,返回不一样的返回值
        if(ex instanceof MissingServletRequestParameterException){
            return Result.error(400, 0, "全局异常捕捉:缺少必需参数:"
                    +((MissingServletRequestParameterException) ex).getParameterName());
        }
        else if(ex instanceof MyException){
           return Result.error(400, 0, "全局异常捕捉:这是自定义异常");
        }
        return Result.error(400, 0, "全局异常捕捉:未知异常");
    }
}

线程池配置AsyncConfiguration.java

package com.test.redis.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;

/** <p>Title: PersonService </p>
 * <p>Description: 线程池配置</p>
 *
 * @author houpeibin
 * @date 2020-2-20 下午7:15:30
 * @version V1.0
 */
@Configuration
@EnableAsync  // 启用异步任务
public class AsyncConfiguration {

    // 声明一个线程池(并指定线程池的名字)
    @Bean("taskExecutor")
    public Executor asyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //核心线程数5:线程池创建时候初始化的线程数
        executor.setCorePoolSize(50);
        //最大线程数5:线程池最大的线程数,只有在缓冲队列满了之后才会申请超过核心线程数的线程
        executor.setMaxPoolSize(500);
        //缓冲队列500:用来缓冲执行任务的队列
        executor.setQueueCapacity(500);
        //允许线程的空闲时间60秒:当超过了核心线程出之外的线程在空闲时间到达之后会被销毁
        executor.setKeepAliveSeconds(60);
        //线程池名的前缀:设置好了之后可以方便我们定位处理任务所在的线程池
        executor.setThreadNamePrefix("DailyAsync-");
        executor.initialize();
        return executor;
    }
}

TestDataEntity.java

package com.test.redis.entity;

import com.alibaba.fastjson.JSONObject;

import java.util.UUID;

/**
 * 测试数据类
 */
public class TestDataEntity {
    static String testStringData;
    static{
        StringBuffer sb = new StringBuffer();
        for(int i=0;i<100;++i){
            sb.append("测试");
        }
        testStringData = sb.toString();
    }

    public static String getTestStringData(String type){
        JSONObject obj = new JSONObject();
        obj.put("type",type);
        obj.put("uuid",UUID.randomUUID());
        obj.put("data",testStringData);
        return obj.toString();
    }

    public static String getKey(int index, String type){
        return "rtd:" + index + ":" + type;
    }
}

7. 测试

打开http://localhost:8080/swagger-ui.html#/

7.1 插入数据测试

首先从http://localhost:8080/swagger-ui.html#/ 测试界面中,找到“单个String数据插入”接口:/insertStringData

点击“Try it out”,

执行结果在图形的下面,如下图

依照此方法依次测试insertStringDataPipelined和insertStringDataPipelinedByRedisTemplate接口

单位:ms

个数jedis单次写入jedis批量写入RedisTemplate批量写入
3000个1922854
30000个2432242539
100000个60617621988
300000个1920322627015

一个数据的长度为:

{"data":"测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试","type":"1","uuid":"aa5b34ba-dd43-4d93-a795-485a0683be7a"}
7.2 读取数据测试

依照此方法依次测试getValueBykey 和getDataByPipelinedAndPipelineKey 、getDataByPipelinedByRedisTemplate接口

单位:ms

个数jedis单次读取jedis批量读取RedisTemplate批量读取
3000个489224308
30000个2030331891
100000个65306892247
300000个1808916229253
7.3 多线程读取数据测试

先插入3000条数据类型为4的数据,便于并发测试:

然后启动5个线程:

查看后台日志:

依次按照如下表格的次数进行测试,记录如下:

个数平均耗时
5个162
10个336
20个668
50个1679
100个1399
200个1604
500个1506

并发测试时,因此同时启动100线程占用时间,一旦线程运行之后,访问redis的时间基本都在1000-2000ms之间。

8.结论

通过读取对比:

  1. 单次读写,性能最差
  2. jedis性能比RedisTemplate的性能好3倍,并且随着数据量的增大,倍数也成指数增加
    因此优先选择jedis,因为他在性能方面完胜RedisTemplate

并发测试:

  1. 并发访问时,对于多线程的开销较大,而对于并发访问redis的性能影响较小。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值