推荐使用Docker来搭建Redis环境.
连接的两种方式
会使用以下方式来操作Redis:
- Lettuce:Lettuce是基于Netty和Reactor的可伸缩线程安全的Redis客户端。Lettuce提供了同步,异步和反应的API来与Redis进行交互。
- Spring Data Redis:可以与Lettuce及其它Redis客户端整合.(暂未提供,待补充)
注意: 在Lettuce中,目前只提供了同步/异步的方式与Redis交互,暂无提供反应式方式与Redis交互的计划.
版本
- Redis: 4.*
- Lettuce:5.*
- Java:1.8 +(未在Java 1.9 中测试,不保证不会出现问题 – 2018/01/17)
- Maven:3.5
完整源码地址在: Gitee仓库
单独使用Lettuce
请注意,该示例为一个Maven项目.
异步请求
异步使用的部分代码如下:
/**
* Redis事务使用异步执行
* <p>
* 方法会删除在本方法内添加的部分数据,具体看方法内部.
*/
public static void asyncTransactionsSetAndGetData() throws ExecutionException, InterruptedException {
// 设置Redis连接信息
RedisURI redisURI = RedisURI.Builder.redis(AppConfig.REDIS_HOST, AppConfig.REDIS_PORT)
.withPassword(AppConfig.REDIS_PASSWORD).withDatabase(AppConfig.REDIS_DATABASE).build();
// 用连接信息,创建Redis客户端
RedisClient redisClient = RedisClient.create(redisURI);
// 获取异步执行命令(这一步很关键)
RedisAsyncCommands<String, String> asyncCommands = redisClient.connect().async();
// 开启事务
RedisFuture<String> stringRedisFuture = asyncCommands.multi();
System.out.println("开启事务的执行反馈:" + stringRedisFuture.get());
RedisFuture<String> rf = asyncCommands.set("MUL-" + AppConfig.DEFAULT_KEY, AppConfig.DEFAULT_VALUE);
int count = 20;
for (int i = 0; i < count; i++) {
asyncCommands.incr("MUL-COUNT");
asyncCommands.set(i + "-MUL-" + AppConfig.DEFAULT_KEY, i + "," + AppConfig.DEFAULT_VALUE);
}
// 删除刚才添加的数据
for (int i = 0; i < count; i++) {
asyncCommands.del(i + "-MUL-" + AppConfig.DEFAULT_KEY);
}
// 执行事务
RedisFuture<TransactionResult> result = asyncCommands.exec();
System.out.println("事务执行结果:" + result.get());
System.out.println("命令执行结果:" + rf.get());
redisClient.shutdownAsync();
}
/**
* 异步执行批量设置及获取数据
* <p>
* <p>
* 未删除本方法内添加的数据.
*/
public static void asyncBatchSetAndGetData() {
// 设置Redis连接信息
RedisURI redisURI = RedisURI.Builder.redis(AppConfig.REDIS_HOST, AppConfig.REDIS_PORT)
.withPassword(AppConfig.REDIS_PASSWORD).withDatabase(AppConfig.REDIS_DATABASE).build();
// 用连接信息,创建Redis客户端
RedisClient redisClient = RedisClient.create(redisURI);
// 获取异步执行命令(这一步很关键)
RedisAsyncCommands<String, String> asyncCommands = redisClient.connect().async();
int count = 10;
List<RedisFuture<String>> futures = new ArrayList<>(count);
for (int i = 0; i < count; i++) {
futures.add(asyncCommands.set(AppConfig.DEFAULT_KEY + "-" + i, AppConfig.DEFAULT_VALUE + i));
}
System.out.println(LettuceFutures.awaitAll(1, TimeUnit.MINUTES, futures.toArray(new RedisFuture[futures.size()])));
List<RedisFuture<String>> lists = new ArrayList<>(count);
for (int i = 0; i < count; i++) {
lists.add(asyncCommands.get(AppConfig.DEFAULT_KEY + "-" + i));
}
lists.stream().filter(x -> !"".equals(x.getError())).forEach(y -> {
try {
System.out.println(y.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
});
redisClient.shutdownAsync();
}
/**
* 异步设置与获取数据的基本用法
* <p>
* <p>
* 方法内部会删除本方法添加的数据.
*
* @throws ExecutionException
* @throws InterruptedException
*/
public static void asyncSetAndGetData() throws ExecutionException, InterruptedException {
// 设置Redis连接信息
RedisURI redisURI = RedisURI.Builder.redis(AppConfig.REDIS_HOST, AppConfig.REDIS_PORT)
.withPassword(AppConfig.REDIS_PASSWORD).withDatabase(AppConfig.REDIS_DATABASE).build();
// 用连接信息,创建Redis客户端
RedisClient redisClient = RedisClient.create(redisURI);
// 获取异步执行命令(这一步很关键)
RedisAsyncCommands<String, String> asyncCommands = redisClient.connect().async();
// 设置数据
Future<String> setResult = asyncCommands.set(AppConfig.DEFAULT_KEY, AppConfig.DEFAULT_VALUE);
System.out.println(setResult.get());
// 读取数据
Future<String> getResult = asyncCommands.get(AppConfig.DEFAULT_KEY);
System.out.println(getResult.get());
// 删除数据,可以传递多个key.
asyncCommands.del(AppConfig.DEFAULT_KEY);
/*
* 关闭此客户端并异步关闭所有打开的连接。
* 调用此方法后客户端的操作被丢弃。
* 关机时间为2秒,超时时间为15秒。
*/
redisClient.shutdownAsync();
}
/**
* 异步设置与获取数据的高级用法.
* <p>
* 方法内部会删除本方法添加的数据.
*
* @throws ExecutionException
* @throws InterruptedException
*/
public static void asyncAdvancedSetAndGetData() throws ExecutionException, InterruptedException {
// 设置Redis连接信息
RedisURI redisURI = RedisURI.Builder.redis(AppConfig.REDIS_HOST, AppConfig.REDIS_PORT)
.withPassword(AppConfig.REDIS_PASSWORD).withDatabase(AppConfig.REDIS_DATABASE).build();
// 用连接信息,创建Redis客户端
RedisClient redisClient = RedisClient.create(redisURI);
// 获取异步执行命令(这一步很关键)
RedisAsyncCommands<String, String> asyncCommands = redisClient.connect().async();
// 编解码器
StringCodec codec = StringCodec.UTF8;
// 状态消息输出
StatusOutput sot = new StatusOutput<>(codec);
// 添加命令
RedisFuture<String> response = asyncCommands.dispatch
(CommandType.SET, sot,
new CommandArgs<>(codec).addKey(AppConfig.DEFAULT_KEY)
.addValue(AppConfig.DEFAULT_VALUE));
// 可以检查是否已经执行完成(执行完成不表示执行成功与否)
if (response.isDone()) {
// 会返回执行结果
System.out.println(response.get());
}
// 获取刚才设置的结果
RedisFuture<String> getInfo = asyncCommands.dispatch(CommandType.GET, sot,
new CommandArgs<>(codec)
.addKey(AppConfig.DEFAULT_KEY));
// 下面会显示上面设置的值:
System.out.println(getInfo.get());
// 删除键值
System.out.println("删除结果(已删除的键数量):"+asyncCommands.dispatch(CommandType.DEL, new IntegerOutput<>(codec),
new CommandArgs<>(codec)
.addKey(AppConfig.DEFAULT_KEY)).get());
/*
* 关闭这个客户端并关闭所有打开的连接。 调用关机后应该丢弃客户端。 关机没有安静的时间和2秒的超时。
*/
redisClient.shutdown();
}
同步请求
同步请求处理的部分代码:
/**
* Redis事务使用同步执行
* <p>
* 方法会删除在本方法内添加的部分数据,具体看方法内部.
*/
public static void syncTransactionsSetAndGetData() {
// 设置Redis连接信息
RedisURI redisURI = RedisURI.Builder.redis(AppConfig.REDIS_HOST, AppConfig.REDIS_PORT)
.withPassword(AppConfig.REDIS_PASSWORD).withDatabase(AppConfig.REDIS_DATABASE).build();
// 用连接信息,创建Redis客户端
RedisClient redisClient = RedisClient.create(redisURI);
// 获取同步执行命令(这一步很关键)
RedisCommands<String, String> redisCommands = redisClient.connect().sync();
// 开启事务
String stringRedisFuture = redisCommands.multi();
System.out.println("开启事务的执行反馈:" + stringRedisFuture);
String rf = redisCommands.set("MUL-" + AppConfig.DEFAULT_KEY, AppConfig.DEFAULT_VALUE);
int count = 20;
for (int i = 0; i < count; i++) {
redisCommands.incr("MUL-COUNT");
redisCommands.set(i + "-MUL-" + AppConfig.DEFAULT_KEY, i + "," + AppConfig.DEFAULT_VALUE);
}
// 删除刚才添加的数据
for (int i = 0; i < count; i++) {
redisCommands.del(i + "-MUL-" + AppConfig.DEFAULT_KEY);
}
// 执行事务
TransactionResult result = redisCommands.exec();
System.out.println("事务执行结果:" + result.get(0));
System.out.println("命令执行结果:" + rf);
redisClient.shutdown();
}
/**
* 同步设置与获取数据的基本用法
* <p>
* <p>
* 方法内部会删除本方法添加的数据.
*
* @throws ExecutionException
* @throws InterruptedException
*/
public static void syncSetAndGetData(){
// 设置Redis连接信息
RedisURI redisURI = RedisURI.Builder.redis(AppConfig.REDIS_HOST, AppConfig.REDIS_PORT)
.withPassword(AppConfig.REDIS_PASSWORD).withDatabase(AppConfig.REDIS_DATABASE).build();
// 用连接信息,创建Redis客户端
RedisClient redisClient = RedisClient.create(redisURI);
// 获取同步执行命令(这一步很关键)
RedisCommands<String, String> redisCommands = redisClient.connect().sync();
// 设置数据
String setResult = redisCommands.set(AppConfig.DEFAULT_KEY, AppConfig.DEFAULT_VALUE);
System.out.println(setResult);
// 读取数据
String getResult = redisCommands.get(AppConfig.DEFAULT_KEY);
System.out.println(getResult);
// 删除数据,可以传递多个key.
redisCommands.del(AppConfig.DEFAULT_KEY);
/*
* 关闭此客户端并同步关闭所有打开的连接。
* 调用此方法后客户端的操作被丢弃。
* 关机时间为2秒,超时时间为15秒。
*/
redisClient.shutdown();
}
/**
* 同步设置与获取数据的高级用法.
* <p>
* 方法内部会删除本方法添加的数据.
*
* @throws ExecutionException
* @throws InterruptedException
*/
public static void syncAdvancedSetAndGetData() {
// 设置Redis连接信息
RedisURI redisURI = RedisURI.Builder.redis(AppConfig.REDIS_HOST, AppConfig.REDIS_PORT)
.withPassword(AppConfig.REDIS_PASSWORD).withDatabase(AppConfig.REDIS_DATABASE).build();
// 用连接信息,创建Redis客户端
RedisClient redisClient = RedisClient.create(redisURI);
// 获取同步执行命令(这一步很关键)
RedisCommands<String, String> redisCommands = redisClient.connect().sync();
// 编解码器
StringCodec codec = StringCodec.UTF8;
// 状态消息输出
StatusOutput sot = new StatusOutput<>(codec);
// 添加命令
Object response = redisCommands.dispatch
(CommandType.SET, sot,
new CommandArgs<>(codec).addKey(AppConfig.DEFAULT_KEY)
.addValue(AppConfig.DEFAULT_VALUE));
System.out.println(response);
///
// 获取刚才设置的结果
Object getInfo = redisCommands.dispatch(CommandType.GET, sot,
new CommandArgs<>(codec)
.addKey(AppConfig.DEFAULT_KEY));
// 下面会显示上面设置的值:
System.out.println(getInfo);
// 删除键值
System.out.println("删除结果(已删除的键数量): " + redisCommands.dispatch(CommandType.DEL, new IntegerOutput(codec),
new CommandArgs<>(codec)
.addKey(AppConfig.DEFAULT_KEY)).toString());
/*
* 关闭这个客户端并关闭所有打开的连接。 调用关机后应该丢弃客户端。 关机没有安静的时间和2秒的超时。
*/
redisClient.shutdown();
}
Spring Data Redis和Lettuce搭配使用
请注意,该示例为一个Spring Boot项目.
部分示例代码如下:
private static final String DEFAULT_KEY = "SUANCAIYU.XYZ-SPRINGBOOT";
@Autowired
private StringRedisTemplate stringRedisTemplate;
@RequestMapping("writeSync")
private String writeSync(){
int length=5000;
for (int i = 0; i <length ; i++) {
stringRedisTemplate.opsForValue().set(DEFAULT_KEY+i,i+DEFAULT_KEY+i);
}
System.out.println("abc");
return "sync";
}
@RequestMapping("asyncRead")
private String read() {
return stringRedisTemplate.execute((RedisCallback<String>) redisConnection -> {
System.out.println(redisConnection.setCommands().sMembers(DEFAULT_KEY.getBytes()).stream().map(x->new String(x)).collect(Collectors.joining(",")));
return "success";
});
}
@RequestMapping("asyncWrite")
private String write() {
stringRedisTemplate.execute((RedisCallback<String>) redisConnection -> {
Long add = redisConnection.setCommands().sAdd(DEFAULT_KEY.getBytes(), "test123456".getBytes());
if (add > 0) {
return "success";
}
return "faild";
});
return "write";
}
完整源码地址在: Gitee仓库