推荐使用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仓库