当前位置:网站首页>[netty] is it difficult to implement a redis client by yourself?
[netty] is it difficult to implement a redis client by yourself?
2022-04-21 19:34:00 【Leng Huanyuan】
Netty: simulation Redis The client of
because redis It is deployed on the server We only need to simulate the client to send the request, so we only need to write the code of the client
Pre knowledge
Before writing, we need to know redis Request specification for
Redis Communication for It is necessary to follow RESP Agreed
Example :
set hello 123
*3\r\n $3 \r\n set \r\n hello \r\n 123
establish channel After the passage Send a command to the server This is the time to write data 【 Output 】 In the war handler Add logic to After receiving the response At this time, the data needs to 【 Input 】 Put it on the stack handler in In the stack handler Add logic to
Netty in Redis The type corresponding to the command
- A single
- error
- Plastic figure
- Batch reply
- Multiple batch replies
client
We just need to write the client . Request to build redis The server can accept and transmit data
The client is still a common way to write
public class RedisClient {
private static final String HOST = "xxxxxxxxx";
private static final int PORT = 6379;
public static void main(String[] args) {
NioEventLoopGroup bossGroup = new NioEventLoopGroup();
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(bossGroup)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
// call netty Support provided netty Codec of protocol
// RedisBulkStringAggregator and RedisarrayAggregator It is an aggregator of two special formats in the protocol
ChannelPipeline pipeline = socketChannel.pipeline();
pipeline.addLast(new RedisDecoder());
pipeline.addLast(new RedisBulkStringAggregator());
pipeline.addLast(new RedisArrayAggregator());
pipeline.addLast(new RedisEncoder());
// Our own processor
pipeline.addLast(new RedisClientHandler());
}
});
try {
ChannelFuture syncFuture = bootstrap.connect(HOST, PORT).sync();
System.out.println("enter redis commands");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
for (; ; ) {
String input = bufferedReader.readLine();
// Exit task
if ("quit".equals(input)) {
syncFuture.channel().close().sync();
break;
}
syncFuture.channel().writeAndFlush(input).sync();
}
syncFuture.channel().closeFuture().sync();
} catch (Exception e) {
e.printStackTrace();
} finally {
bossGroup.shutdownGracefully();
}
}
}
processor
Because to read and write So we need to integrate hybrid processor classes : ChannelDuplexHandler
We need to judge five request types So first encapsulate a method of class output
RedisMessage Netty Provided redis The information object of , The following five types come from it
private void printRedisResponse(RedisMessage msg) {
if (msg instanceof SimpleStringRedisMessage) {
SimpleStringRedisMessage tmpMsg = (SimpleStringRedisMessage) msg;
System.out.println(tmpMsg.content());
} else if (msg instanceof ErrorRedisMessage) {
ErrorRedisMessage tmpMsg = (ErrorRedisMessage) msg;
System.out.println(tmpMsg.content());
} else if (msg instanceof IntegerRedisMessage) {
IntegerRedisMessage tmpMsg = (IntegerRedisMessage) msg;
System.out.println(tmpMsg.value());
} else if (msg instanceof FullBulkStringRedisMessage) {
FullBulkStringRedisMessage tmpMsg = (FullBulkStringRedisMessage) msg;
if (tmpMsg.isNull()) {
return;
}
System.out.println(tmpMsg.content().toString(CharsetUtil.UTF_8));
} else if (msg instanceof ArrayRedisMessage) {
ArrayRedisMessage tmpMsg = (ArrayRedisMessage) msg;
for (RedisMessage child : tmpMsg.children()) {
printRedisResponse(child);
}
}
// If so, should exceptions be thrown
}
Write orders
// Write
// Out of the stack handler The common method of
// Need to deal with redis command
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
// The string passed in by the keyboard Such as : keys *
String commandStr = (String) msg;
// Separate commands with spaces
String[] commandArr = commandStr.split("\\s+");
// Accept redis List of commands RedisMessag Save the contents of the command
List<RedisMessage> redisMessageList = new ArrayList<>(commandArr.length);
for (String cmdStr : commandArr) {
FullBulkStringRedisMessage message = new FullBulkStringRedisMessage(
ByteBufUtil.writeUtf8(ctx.alloc(), cmdStr));
redisMessageList.add(message);
}
// The command to separate Merge into one complete command
RedisMessage request = new ArrayRedisMessage(redisMessageList);
// Write channel
ctx.write(request, promise);
}
Read command
// Read
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// When accepting this value Is that we store redismessage The object of
RedisMessage redisMessage = (RedisMessage) msg;
// The results returned are of different types Treat separately
printRedisResponse(redisMessage);
// Memory management uses The way of reference counting So we need to release resources
ReferenceCountUtil.release(redisMessage);
}
Demonstration effect

版权声明
本文为[Leng Huanyuan]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/04/202204211927509935.html
边栏推荐
猜你喜欢
随机推荐
Seata (I) service configuration and startup
leetcode344. 反转字符串
改进模型速度/精度的工程方法
[hand pose estimation] [paper interpretation] 3D human pose estimation in rgbd images for robotic task learning
Leetcode0886. 可能的二分法(medium,二分图)
Use the mremoting tool to manage all remote connections
leetcode541. 反转字符串 II
Comparison of F (ab ') 2 IgG isotype in abbexa goat
int count= cmd.ExecuteNonQuery();附近有一条语法错误
Release announcement of HMS core version 6.4.0
31 - Gru principle and source code line by line implementation
C language quick sorting problem
影响VPS网站优化的因素有哪些?
redis安装与配置开机自启
AAAI 2022 更细粒度的不实信息检测
Sleuth + Zipkin link tracking
C# 不能用于文件名的字符
Flynk shunt
The CPU and memory consumption are too high, but the memory and CPU occupied by the processes in the task manager cannot be seen
Linux Centos7 安装MySql8 (简单、实测可行)







