Vert.x-Redis是Vertx官方提供的一个Redis的无阻塞异步调用库,本文基于3.8.1
版本来介绍Vert.x-Redis的核心API
RedisOptions
用于指定创建redis连接的配置,这里使用的是io.vertx.redis.client包下的而非io.vertx.redis包下的RedisOptions,后者包装的是vertx 基本网络连接的配置,可以设置为前者的netClientOptions字段
重要字段
endpoints
: Redis的地址和端口type
: Redis的连接类型(STANDALONE,SENTINEL,CLUSTER)netClientOptions
:基本网络配置,不设置会使用默认构造器创建
Redis
所有RedisClient实现的抽象接口,提供了默认静态构造方法创建具体RedisClient,默认为STANDALONE,带RedisOptions的构造方法会根据RedisOptions中的type来决定具体实例化RedisClient的类型
创建Redis对象的默认静态构造方法源码
static Redis createClient(Vertx vertx, RedisOptions options) {
switch (options.getType()) {
case STANDALONE:
return RedisClient.create(vertx, options);
case SENTINEL:
return RedisSentinelClient.create(vertx, options);
case CLUSTER:
return RedisClusterClient.create(vertx, options);
default:
throw new IllegalStateException("Unknown Redis Client type: " + options.getType());
}
}
初始化连接
在执行命令之前必须先调用connect()方法来建立连接,使用连接未建立的client执行命令时返回的response为空
一个完整的从定义到调用的示例
Redis.createClient(
vertx,
new RedisOptions()
.setType(RedisClientType.SENTINEL)
.addEndpoint(SocketAddress.inetSocketAddress(5000, "127.0.0.1"))
.addEndpoint(SocketAddress.inetSocketAddress(5001, "127.0.0.1"))
.addEndpoint(SocketAddress.inetSocketAddress(5002, "127.0.0.1"))
.setMasterName("sentinel7000")
.setRole(RedisRole.MASTER))
.connect(onConnect -> {
// assuming we got a connection to the master node
// query the info for the node
onConnect.result()
.send(Request.cmd(Command.INFO), info -> {
// do something...
});
});
RedisAPI
RedisAPI接口中定义了redis中所有常见命令方法,它的默认静态构造方法接收一个Redis的实例,创建并返回一个RedisAPIImpl对象,RedisAPIImpl持有传入的Redis实例,并实现了所有命令方法都要调用的send方法
使用RedisAPI执行命令示例
RedisAPI api = RedisAPI.api(redisClient);
api.keys("*",info -> {
// do something...
});
Result类型
执行Redis命令异步返回Future:AsyncResult
SimpleStringType
: 简易字符串类型,默认值为OK,一般无具体返回结果的命令(例如set
)的结果就会用此类型包装IntegerType
数字类型,一般返回结果一定是数字的命令(例如incr
)结果会用此类型包装BulkType
基本对象类型,一般有具体单一返回结果的命令(例如get
)都会用此类型包装MultiType
数组类型,有多个返回结果的命令(例如list
)都会用此类型包装,也是唯一可迭代的类型ErrorType
异常类型,该类型包装的是Vertx Redis工具类所抛出的异常而非Redis本身返回的异常,Redis本身返回的异常将会被封装在AsyncResult的throwable中
Response接口继承了Iterable,但这并不意味着所有的Response实现类都是可迭代的,事实上,只有MultiType是可迭代的,其它实现的迭代相关方法都在Response中default实现成抛出UnsupportedOperationException
异常
哨兵实现
Vertx Redis哨兵客户端的实现实际是使用了装饰模式加强了单节点的redis客户端,哨兵客户端持有一个单节点客户端和一个哨兵客户端,哨兵客户端订阅哨兵消息,当收到消息后会通过redisClient的fail()方法传入消息触发注册在redisClient上的OnException函数处理消息从而完成响应哨兵消息,核心代码如下:
sentinel
.handler(msg -> {
if (msg.type() == ResponseType.MULTI) {
if ("MESSAGE".equalsIgnoreCase(msg.get(0).toString())) {
// we don't care about the payload
if (redis != null) {
redis.fail(ErrorType.create("SWITCH-MASTER Received +switch-master message from Redis Sentinel."));
} else {
LOG.warn("Received +switch-master message from Redis Sentinel.");
}
}
}
});