前言
这个系列的文章,基于Redisson版本3.13.2
Redisson是redis的一个客户端组件,依赖于netty网络框架,实现高并发读写redis缓存。redisson中的线程池主要有两类,一个是nettyThread【EventLoopGroup】和threads【ExecutorService】。从实现类来看,可以得知前一个是netty中封装过的线程池,后一个是java原生的线程池;
定义
threads:
Threads amount shared across all listeners of RTopic object, invocation handlers of RRemoteService object and RExecutorService tasks.
主要用于消费订阅、远程方法调用和框架内的一些任务调度;还有就是redis数据的解码环节【特定场景】、RedissonMap中如果用到了Read-through、Write-through和Write-behind策略,也会用到此线程池;
nettyThreads:
Threads amount shared between all redis clients used by Redisson.
主要用于redis客户端的网络通讯,发送命令和接收返回数据;
线程池初始化
源代码位于MasterSlaveConnectionManager.class类中。
nettyThreads的初始化 -- 175行
if (cfg.getEventLoopGroup() == null) {
this.group = new EpollEventLoopGroup(cfg.getNettyThreads(), new DefaultThreadFactory("redisson-netty"));
} else {
this.group = cfg.getEventLoopGroup();
}
threads的初始化 -- 215行
if (cfg.getExecutor() == null) {
int threads = Runtime.getRuntime().availableProcessors() * 2;
if (cfg.getThreads() != 0) {
threads = cfg.getThreads();
}
executor = Executors.newFixedThreadPool(threads, new DefaultThreadFactory("redisson"));
} else {
executor = cfg.getExecutor();
}
使用场景举例
nettyThreads
创建redis客户端时,使用了公用nettyThreads线程池,所有的redis client会使用同一个线程组进行收发消息。源代码位于RedisClient.class 125行。
private Bootstrap createBootstrap(RedisClientConfig config, Type type) {
Bootstrap bootstrap = new Bootstrap()
.resolver(config.getResolverGroup())
.channel(config.getSocketChannelClass())
// 公用nettyThreads线程池
.group(config.getGroup());
bootstrap.handler(new RedisChannelInitializer(bootstrap, config, this, channels, type));
bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, config.getConnectTimeout());
bootstrap.option(ChannelOption.SO_KEEPALIVE, config.isKeepAlive());
bootstrap.option(ChannelOption.TCP_NODELAY, config.isTcpNoDelay());
config.getNettyHook().afterBoostrapInitialization(bootstrap);
return bootstrap;
}
threads
消费订阅模式下,接收消息时,会根据消息的类型,分发到列表中的各个订阅者。源代码位于CommandPubSubDecoder.class 142行。
@Override
protected void decodeResult(CommandData<Object, Object> data, List<Object> parts, Channel channel,
Object result) throws IOException {
// ignore ...
executor.execute(new Runnable() {
@Override
public void run() {
if (result instanceof PubSubStatusMessage) {
pubSubConnection.onMessage((PubSubStatusMessage) result);
} else if (result instanceof PubSubMessage) {
pubSubConnection.onMessage((PubSubMessage) result);
} else if (result instanceof PubSubPatternMessage) {
pubSubConnection.onMessage((PubSubPatternMessage) result);
}
}
});
// ignore ...
}
注:
解码使用线程池的代码见CommandDecoder.class 122行