高并发三大法宝之 缓存,消息队列,异步任务
1.缓存(常用redis)
将热点数据或者经常需要进行read的数据放到redis或者其他缓存中,可以极大的降低数据库的压力,遇到流量高峰时,不至于一下子就把数据库压垮了,使用springcache配合redis继续使用,也可以很方便的对数据进行缓存。
springcache 几个常用注解
@Cacheable(value = "groupName",key = "keyName") // 对数据进行缓存
@CacheEvict(value = "groupName",allEntries = true or false) // 对缓存数据进行删除
springcache使用时需要配置缓存类型
spring.cache.type=redis
config
@EnableConfigurationProperties(CacheProperties.class)
@EnableCaching
@Configuration
public class MyCacheConfiguration {
@Bean
public RedisCacheConfiguration redisCacheConfiguration(CacheProperties cacheProperties){
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
// 设置序列化器
config = config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()));
config = config.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
CacheProperties.Redis redisProperties =cacheProperties.getRedis();
// 设置ttl
if(redisProperties.getTimeToLive() != null){
config = config = config.entryTtl(redisProperties.getTimeToLive());
}
if(redisProperties.getKeyPrefix() != null){
config = config.prefixKeysWith(redisProperties.getKeyPrefix());
}
if(!redisProperties.isCacheNullValues()){
config = config.disableCachingNullValues();
}
if(!redisProperties.isUseKeyPrefix()){
config = config.disableKeyPrefix();
}
return config;
}
}
2.异步
使用线程池搭配异步编排可以对业务进行高效的分段处理
普通线程池配置
@EnableConfigurationProperties(value = ThreadPoolConfigProperties.class) // 开启属性配置
@Configuration
public class MyThreadConfig {
@Bean
public ThreadPoolExecutor threadPoolExecutor(ThreadPoolConfigProperties poolConfigProperties) {
return new ThreadPoolExecutor(
poolConfigProperties.getCoreSize(),
poolConfigProperties.getMaxSize(),
poolConfigProperties.getKeepAliveTime(),
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(1000),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
}
}
将参数动态的配置到yaml文件中
@ConfigurationProperties(prefix = "mall.thread")
@Component
@Data
@Primary
public class ThreadPoolConfigProperties {
private Integer coreSize;
private Integer maxSize;
private Integer keepAliveTime;
}
gulimall:
thread:
core-size: 20
max-size: 200
keep-alive-time: 10
将任务分多个组进行异步执行将提升代码效率,以下为示例效果
@Resource
ThreadPoolExecutor excutor;
Result result = new Result();
CompletableFuture<Void> task1 = CompletableFuture.runAsync(() -> {
// ...... 业务代码 逻辑1
}, excutor);
CompletableFuture<Void> task2 = task1.thenRunAsync(()->{
// ...... 业务代码 逻辑2
},excutor);
CompletableFuture<Void> task3 = task2.thenRunAsync(() -> {
// ...... 业务代码 逻辑3
}, excutor);
try {
// 等待所有的任务执行完成一同返回
CompletableFuture.allOf(task1, task2,task3).get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
// this is your result return
return result;
3.消息队列
将大流量放到消息队列中,主流的像kafka,rabbitmq,activemq等,这里使用rabbitmq