SpringBoot与Redis多线程入门——多线程redis存取数据

  1. SpringBoot Redis yml 配置

此处省略密码

spring:
  redis:
    database: 0
    host: 127.0.0.1
    port: 6379
    timeout: 3000
    jedis:
      pool:
        max-active: 8
        max-wait: -1
        max-idle: 8
        min-idle: 0
  1. RedisCofig.java 配置类代码
@EnableCaching
@Configuration
public class RedisConfig {

    @Value("${spring.redis.host}")
    private String host;
    @Value("${spring.redis.database}")
    private Integer database;
    @Value("${spring.redis.port}")
    private Integer port;

    @Primary
    @Bean(name = "jedisPoolConfig")
    @ConfigurationProperties(prefix = "spring.redis.pool")
    public JedisPoolConfig jedisPoolConfig() {
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxWaitMillis(10000);
        return jedisPoolConfig;
    }

    @Bean
    public RedisConnectionFactory redisConnectionFactory(JedisPoolConfig jedisPoolConfig) {
        RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
        redisStandaloneConfiguration.setHostName(host);
        redisStandaloneConfiguration.setDatabase(database);
        // redisStandaloneConfiguration.setPassword(pwd);
        redisStandaloneConfiguration.setPort(port);
        JedisClientConfiguration.JedisPoolingClientConfigurationBuilder jpcb = (JedisClientConfiguration.JedisPoolingClientConfigurationBuilder) JedisClientConfiguration.builder();
        jpcb.poolConfig(jedisPoolConfig);
        JedisClientConfiguration jedisClientConfiguration = jpcb.build();
        return new JedisConnectionFactory(redisStandaloneConfiguration, jedisClientConfiguration);
    }

    /**
     * 配置redisTemplate针对不同key和value场景下不同序列化的方式
     * 此处针对key为String,value为CustomerVo对象的序列化方式
     * @param factory Redis连接工厂
     * @return
     */
    @Primary
    @Bean(name = "customerRedisTemplate")
    public RedisTemplate customerRedisTemplate(RedisConnectionFactory factory) {
        RedisTemplate template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        template.setKeySerializer(stringRedisSerializer);
        template.setHashKeySerializer(stringRedisSerializer);
                // 这里是关键,注意替换为自己的类
        Jackson2JsonRedisSerializer redisSerializer = new Jackson2JsonRedisSerializer<>(CustomerVo.class);
        template.setValueSerializer(redisSerializer);
        template.setHashValueSerializer(redisSerializer);
        template.afterPropertiesSet();
        return template;
    }

    @Bean(name = "doctorRedisTemplate")
    public RedisTemplate doctorRedisTemplate(RedisConnectionFactory factory) {
        RedisTemplate template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        template.setKeySerializer(stringRedisSerializer);
        template.setHashKeySerializer(stringRedisSerializer);
        Jackson2JsonRedisSerializer redisSerializer = new Jackson2JsonRedisSerializer<>(DoctorVo.class);
        template.setValueSerializer(redisSerializer);
        template.setHashValueSerializer(redisSerializer);
        template.afterPropertiesSet();
        return template;
    }

    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnSingleCandidate(RedisConnectionFactory.class)
    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }
}
  1. Vo类和Service类代码

CustomerVo.java

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class CustomerVo {
    private Integer customerId;
    private String queueSeq;
    private String customerName;
    private String customerSex;

    @Override
    public String toString() {
        return "CustomerVo{" +
                "queueSeq='" + queueSeq + '\'' +
                ", customerName='" + customerName + '\'' +
                ", customerSex='" + customerSex + '\'' +
                '}';
    }
}

Service

@Slf4j
@Service
public class RedisLookupService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Async("taskExecutor")
    public CompletableFuture enqueueCustomer(CustomerVo customer) {
        Long result = redisTemplate.opsForList().rightPush("queue", customer);
        log.info("{} 入队..", customer);
        return CompletableFuture.completedFuture(result);
    }

    @Async("taskExecutor")
    public CompletableFuture dequeueCustomer() {
        if (Objects.requireNonNull(redisTemplate.opsForList().size("queue")) < 1) {
            return CompletableFuture.completedFuture(null);
        }
        CustomerVo vo = redisTemplate.opsForList().leftPop("queue");
        log.info("{} 出队...", vo);
        return CompletableFuture.completedFuture(vo);
    }

}

AsyncConfig.java 配置类

因为用到了SpringBoot的多线程,所以要加一下这个配置类

@Configuration
@EnableAsync  // 启用异步任务
public class AsyncConfig {

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

    @GetMapping("/en")
    public String enqueueTry() throws InterruptedException {
        long start = System.currentTimeMillis();
        CustomerVo c1 = new CustomerVo(1, "A031", "马哲", "男");
        CustomerVo c2 = new CustomerVo(2, "A039", "马王", "男");
        CustomerVo c3 = new CustomerVo(3, "A040", "马丽", "女");
        CompletableFuture future1 = service.enqueueCustomer(c1);
        CompletableFuture future2 = service.enqueueCustomer(c3);
        CompletableFuture future3 = service.enqueueCustomer(c2);
        CompletableFuture.allOf(future1, future2, future3).join();
        long end = System.currentTimeMillis();
        log.info("complete test: {}s",(float)(end - start) / 1000);
        return "ok";
    }

    @GetMapping("/qn")
    public String dequeueTry() {
        long start = System.currentTimeMillis();
        CompletableFuture customer1 = service.dequeueCustomer();
        CompletableFuture customer2 = service.dequeueCustomer();
        CompletableFuture customer3 = service.dequeueCustomer();
        CompletableFuture.allOf(customer1, customer2, customer3).join();
        long end = System.currentTimeMillis();
        log.info("complete test: {}s",(float)(end - start) / 1000);
        return "ok";
    }
}

/en的测试结果:
图1

SpringBoot与Redis多线程入门——多线程redis存取数据
图2
SpringBoot与Redis多线程入门——多线程redis存取数据

/qn的测试结果:

SpringBoot与Redis多线程入门——多线程redis存取数据
由此可以发现,多线程已经启动。
  1. 日志设置

yml配置

logging:
  config: classpath:logback.xml
  level:
    com.ravi.mapper: trace

xml配置


            %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n

            ${LOG_HOME}/Slf4j_%d{yyyy-MM-dd}.log

            30

            %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n

            10MB

参考文章大数据从业者

Original: https://www.cnblogs.com/ceeSomething8/p/15934142.html
Author: cee_nil
Title: SpringBoot与Redis多线程入门——多线程redis存取数据

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/711780/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球