一起学习Redis之在Java中使用
操作系统:CentOS-7.8
Redis版本:6.0.5
SpringBoot 2.1.5.RELEASE
Java Version 1.8.0_231
一、使用Redis客户端
Jedis、Redisson和Lettuce都是比较常用的支持连接Redis的客户端,所以在这里我们主要演示这三种客户端如何连接不同的redis模式的redis
1.Jedis
Jedis特点
比较经典的Redis的Java客户端,对Redis的命令支持比较全面
比较轻量和简洁,对其进行改造和集成比较方便
不支持异步,方法调用都是同步的,使用的阻塞IO
客户端实例非线程安全,多线程并发场景下,需要通过连接池来使用客户端
早期版本Spring的默认客户端
使用演示
pom依赖
1<dependency>
2 <groupId>redis.clients</groupId>
3 <artifactId>jedis</artifactId>
4 <version>2.9.3</version>
5</dependency>
Jedis连接单机单实例Redis
1import redis.clients.jedis.Jedis;
2
3/**
4 * @author 爱做梦的锤子
5 * @create 2020/7/17
6 */
7public class SingleInstanceJedis {
8
9
10 private String host;
11 private Integer port;
12 private String password;
13
14 /**
15 * 连接单机单实例的redis
16 *
17 * @param host redis主机地址
18 * @param port redis服务端口
19 * @param password redis认证密码
20 */
21 public SingleInstanceJedis(String host, Integer port, String password) {
22 this.host = host;
23 this.port = port;
24 this.password = password;
25 }
26
27 /**
28 * 连接redis
29 *
30 * @return 一个Jedis客户端
31 */
32 public Jedis connect() {
33 Jedis jedis = new Jedis(host, port);
34 jedis.auth(password);
35 return jedis;
36 }
37
38}
Jedis连接哨兵模式Redis
1import redis.clients.jedis.Jedis;
2import redis.clients.jedis.JedisPoolConfig;
3import redis.clients.jedis.JedisSentinelPool;
4
5import java.util.Set;
6
7/**
8 * @author 爱做梦的锤子
9 * @create 2020/7/17
10 */
11public class SentinelJedis {
12
13 private JedisSentinelPool jedisSentinelPool;
14
15 /**
16 * 连接哨兵模式的redis
17 *
18 * @param masterName redis的master名称
19 * @param sentinels 哨兵的主机和端口信息
20 * @param password redis的认证密码
21 */
22 public SentinelJedis(String masterName, Set<String> sentinels, String password) {
23 //根据redis的信息创建一个redis哨兵的连接池
24 JedisPoolConfig config = new JedisPoolConfig();
25 config.setMaxTotal(10);
26 config.setMaxIdle(5);
27 config.setMinIdle(5);
28 jedisSentinelPool = new JedisSentinelPool(masterName, sentinels, config, password);
29 }
30
31 /**
32 * 从连接池中取出一个客户端
33 *
34 * @return 获取一个Jedis客户端
35 */
36 public Jedis connect() {
37 return jedisSentinelPool.getResource();
38 }
39
40 /**
41 * 销毁连接池
42 */
43 public void close() {
44 jedisSentinelPool.close();
45 jedisSentinelPool.destroy();
46 }
47}
Jedis连接集群模式Redis
1import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
2import redis.clients.jedis.HostAndPort;
3import redis.clients.jedis.JedisCluster;
4
5import java.util.Set;
6
7/**
8 * @author 爱做梦的锤子
9 * @create 2020/7/17
10 */
11public class ClusterJedis {
12
13 private Set<HostAndPort> redisNodes;
14 private String password;
15 private GenericObjectPoolConfig config;
16
17 /**
18 * 连接redis cluster
19 *
20 * @param redisNodes 集群中redis节点信息
21 * @param password redis 密码
22 */
23 public ClusterJedis(Set<HostAndPort> redisNodes, String password) {
24 this.redisNodes = redisNodes;
25 this.password = password;
26 config = new GenericObjectPoolConfig();
27 config.setMaxTotal(10);
28 config.setMaxIdle(5);
29 config.setMinIdle(5);
30 }
31
32 /**
33 * 连接redis cluster
34 *
35 * @return 一个redis cluster客户端
36 */
37 public JedisCluster connect() {
38 JedisCluster jedisCluster = new JedisCluster(redisNodes, 10000, 10000, 3, password, config);
39 return jedisCluster;
40 }
41
42}
以上三段代码是使用Jedis连接三种模式下Redis的简易演示代码,下面再附上测试类代码
测试类
1/**
2 * @author 爱做梦的锤子
3 * @create 2020/7/17
4 */
5
6public class JedisTest {
7
8 private static final Logger LOGGER = LoggerFactory.getLogger(JedisTest.class);
9 private static final String TEST_KEY = "jedis";
10 private static final String TEST_VALUE = "dream-hammer";
11
12 @Test
13 public void singleInstance() {
14 SingleInstanceJedis singleInstanceJedis = new SingleInstanceJedis("192.168.56.90", 6379, "123456");
15 Jedis jedis = singleInstanceJedis.connect();
16 jedis.set(TEST_KEY, TEST_VALUE);
17 LOGGER.info("jedis单机单实例:{}", jedis.get(TEST_KEY));
18 Assert.assertEquals(TEST_VALUE, jedis.get(TEST_KEY));
19 }
20
21 @Test
22 public void sentinel() {
23 Set<String> sentinels = new HashSet<>();
24 sentinels.add("192.168.56.91:26379");
25 sentinels.add("192.168.56.92:26379");
26 sentinels.add("192.168.56.93:26379");
27 SentinelJedis sentinelJedis = new SentinelJedis("redis-master", sentinels, "123456");
28 Jedis jedis = sentinelJedis.connect();
29 jedis.set(TEST_KEY, TEST_VALUE);
30 LOGGER.info("jedis哨兵模式:{}", jedis.get(TEST_KEY));
31 Assert.assertEquals(TEST_VALUE, jedis.get(TEST_KEY));
32 }
33
34 @Test
35 public void cluster() {
36 Set<HostAndPort> redisNodes = new HashSet<>();
37 redisNodes.add(new HostAndPort("192.168.56.81",6379));
38 redisNodes.add(new HostAndPort("192.168.56.82",6379));
39 redisNodes.add(new HostAndPort("192.168.56.83",6379));
40 redisNodes.add(new HostAndPort("192.168.56.84",6379));
41 redisNodes.add(new HostAndPort("192.168.56.85",6379));
42 redisNodes.add(new HostAndPort("192.168.56.86",6379));
43 ClusterJedis clusterJedis = new ClusterJedis(redisNodes, "123456");
44 JedisCluster jedisCluster = clusterJedis.connect();
45 jedisCluster.set(TEST_KEY, TEST_VALUE);
46 LOGGER.info("jedis集群模式:{}", jedisCluster.get(TEST_KEY));
47 Assert.assertEquals(TEST_VALUE, jedisCluster.get(TEST_KEY));
48 }
49}
2.Redisson
Redisson特点
基于Netty实现,使用非阻塞IO,支持异步,性能高
API是线程安全的,可以操作单个Redisson连接来完成多种操作
实现多种分布式和可扩展的Java数据结构,例如,分布式锁,分布式集合,可通过Redis支持延迟队列
Redisson注重分布式和锁的相关功能,所以在基础功能上较为简单,不支持Redis的原生命令操作,比如不支持字符串操作等
使用演示
pom依赖
1<dependency>
2 <groupId>org.redisson</groupId>
3 <artifactId>redisson</artifactId>
4 <version>3.12.5</version>
5</dependency>
redisson连接单机单实例Redis
1import org.redisson.Redisson;
2import org.redisson.api.RedissonClient;
3import org.redisson.config.Config;
4
5/**
6 * @author 爱做梦的锤子
7 * @create 2020/7/17
8 */
9public class SingleInstanceRedisson {
10
11 private Config config;
12
13 /**
14 * 连接单机单实例的redis
15 *
16 * @param host redis主机地址
17 * @param port redis 端口
18 * @param password redis密码
19 */
20 public SingleInstanceRedisson(String host, Integer port, String password) {
21 config = new Config();
22 config.useSingleServer()
23 .setAddress("redis://" + host + ":" + port)
24 .setPassword(password);
25
26 }
27
28 /**
29 * 连接redis
30 *
31 * @return 一个RedissonClient客户端
32 */
33 public RedissonClient connect() {
34 RedissonClient redissonClient = Redisson.create(config);
35 return redissonClient;
36 }
37}
redisson连接哨兵模式Redis
1import org.redisson.Redisson;
2import org.redisson.api.RedissonClient;
3import org.redisson.config.Config;
4
5/**
6 * @author 爱做梦的锤子
7 * @create 2020/7/17
8 */
9public class SentinelRedisson {
10
11 private Config config;
12
13 /**
14 * 连接哨兵模式redis
15 *
16 * @param masterName redis的master名称
17 * @param sentinels 哨兵的连接信息 redis://sentinelHost:sentinelPort
18 * @param password redis密码
19 */
20 public SentinelRedisson(String masterName, String[] sentinels, String password) {
21 config = new Config();
22 config.useSentinelServers()
23 .setMasterName(masterName)
24 .addSentinelAddress(sentinels)
25 .setPassword(password);
26
27 }
28
29 /**
30 * 连接redis
31 *
32 * @return 一个RedissonClient客户端
33 */
34 public RedissonClient connect() {
35 RedissonClient redissonClient = Redisson.create(config);
36 return redissonClient;
37 }
38
39}
redisson连接集群模式Redis
1import org.redisson.Redisson;
2import org.redisson.api.RedissonClient;
3import org.redisson.config.Config;
4
5/**
6 * @author 爱做梦的锤子
7 * @create 2020/7/17
8 */
9public class ClusterRedisson {
10
11 private Config config;
12
13 /**
14 * 连接cluster模式的redis
15 *
16 * @param redisNodes redis集群中节点信息 redis://nodeHost:nodePort
17 * @param password redis密码
18 */
19 public ClusterRedisson(String[] redisNodes, String password) {
20 config = new Config();
21 config.useClusterServers()
22 .addNodeAddress(redisNodes)
23 .setPassword(password);
24
25 }
26
27 /**
28 * 连接redis
29 *
30 * @return 一个RedissonClient客户端
31 */
32 public RedissonClient connect() {
33 RedissonClient redissonClient = Redisson.create(config);
34 return redissonClient;
35 }
36
37}
以上三段代码是使用Redisson连接三种模式下Redis的简易演示代码,下面再附上测试类代码
测试类
1/**
2 * @author 爱做梦的锤子
3 * @create 2020/7/20
4 */
5public class RedissonTest {
6
7 private static final Logger LOGGER = LoggerFactory.getLogger(RedissonTest.class);
8 private static final String TEST_KEY = "redisson";
9 private static final long TEST_VALUE = 100L;
10
11 @Test
12 public void singleInstance() {
13 SingleInstanceRedisson singleInstanceRedisson = new SingleInstanceRedisson("192.168.56.90", 6379, "123456");
14 RedissonClient redissonClient = singleInstanceRedisson.connect();
15 RAtomicLong atomicLong = redissonClient.getAtomicLong(TEST_KEY);
16 atomicLong.set(TEST_VALUE);
17 LOGGER.info("redisson单机单实例:{}", redissonClient.getAtomicLong(TEST_KEY).get());
18 Assert.assertEquals(TEST_VALUE, redissonClient.getAtomicLong(TEST_KEY).get());
19 }
20
21 @Test
22 public void sentinel() {
23 String[] sentinels = new String[]{"redis://192.168.56.91:26379", "redis://192.168.56.92:26379", "redis://192.168.56.93:26379"};
24 SentinelRedisson sentinelRedisson = new SentinelRedisson("redis-master", sentinels, "123456");
25 RedissonClient redissonClient = sentinelRedisson.connect();
26 RAtomicLong atomicLong = redissonClient.getAtomicLong(TEST_KEY);
27 atomicLong.set(TEST_VALUE);
28 LOGGER.info("redisson哨兵模式:{}", redissonClient.getAtomicLong(TEST_KEY).get());
29 Assert.assertEquals(TEST_VALUE, redissonClient.getAtomicLong(TEST_KEY).get());
30 }
31
32 @Test
33 public void cluster() {
34 String[] redisNodes = new String[]{
35 "redis://192.168.56.81:6379",
36 "redis://192.168.56.82:6379",
37 "redis://192.168.56.83:6379",
38 "redis://192.168.56.84:6379",
39 "redis://192.168.56.85:6379",
40 "redis://192.168.56.86:6379"
41 };
42 ClusterRedisson clusterRedisson = new ClusterRedisson(redisNodes, "123456");
43 RedissonClient redissonClient = clusterRedisson.connect();
44 RAtomicLong atomicLong = redissonClient.getAtomicLong(TEST_KEY);
45 atomicLong.set(TEST_VALUE);
46 LOGGER.info("redisson集群模式:{}", redissonClient.getAtomicLong(TEST_KEY).get());
47 Assert.assertEquals(TEST_VALUE, redissonClient.getAtomicLong(TEST_KEY).get());
48 }
49}
3.Lettuce
Lettuce特点
Redis高级客户端,线程安全的,单个Lettuce连接可以在多个线程中操作
基于Netty实现,使用非阻塞IO,支持异步
对Redis基础操作支持全面,相对Jedis来说更加高效,不要考虑太多线程安全问题
相对Redisson来说分布式锁和分布式数据结构等都需要自行实现
Spring现有版本的默认redis客户端
使用演示
pom依赖
1<dependency>
2 <groupId>io.lettuce</groupId>
3 <artifactId>lettuce-core</artifactId>
4 <version>5.1.6.RELEASE</version>
5</dependency>
lettuce连接单机单实例Redis
1import io.lettuce.core.RedisClient;
2import io.lettuce.core.RedisURI;
3import io.lettuce.core.api.StatefulRedisConnection;
4
5/**
6 * @author 爱做梦的锤子
7 * @create 2020/7/20
8 */
9public class SingleInstanceLettuce {
10
11 private RedisURI redisURI;
12
13 /**
14 * 使用Lettuce连接单机单实例的redis
15 * @param host redis的主机地址
16 * @param port redis的端口号
17 * @param password redis的密码
18 */
19 public SingleInstanceLettuce(String host, Integer port, String password) {
20 redisURI = RedisURI.builder()
21 .withHost(host)
22 .withPort(port)
23 .withPassword(password)
24 .build();
25 }
26
27 /**
28 * 连接redis获取一个连接
29 * @return 一个redis连接
30 */
31 public StatefulRedisConnection<String, String> connect() {
32 RedisClient redisClient = RedisClient.create(redisURI);
33 StatefulRedisConnection<String, String> connect = redisClient.connect();
34 return connect;
35 }
36}
lettuce连接哨兵模式redis
1import io.lettuce.core.RedisClient;
2import io.lettuce.core.RedisURI;
3import io.lettuce.core.codec.Utf8StringCodec;
4import io.lettuce.core.masterslave.MasterSlave;
5import io.lettuce.core.masterslave.StatefulRedisMasterSlaveConnection;
6
7import java.util.List;
8
9/**
10 * @author 爱做梦的锤子
11 * @create 2020/7/20
12 */
13public class SentinelLettuce {
14 private List<RedisURI> redisURIList;
15
16 /**
17 * 连接哨兵模式的redis
18 * @param redisURIList 哨兵模式redis下的哨兵的信息,建议使用RedisURI.builder.sentinel填写哨兵信息来进行构造
19 */
20 public SentinelLettuce(List<RedisURI> redisURIList) {
21 this.redisURIList = redisURIList;
22 }
23
24 /**
25 * 连接redis获取一个连接
26 * @return 一个redis的连接
27 */
28 public StatefulRedisMasterSlaveConnection<String, String> connect() {
29 RedisClient redisClient = RedisClient.create();
30 StatefulRedisMasterSlaveConnection<String, String> connect = MasterSlave.connect(redisClient, new Utf8StringCodec(), redisURIList);
31 return connect;
32 }
33}
lettuce连接集群模式Redis
1import io.lettuce.core.RedisURI;
2import io.lettuce.core.cluster.RedisClusterClient;
3import io.lettuce.core.cluster.api.StatefulRedisClusterConnection;
4
5import java.util.List;
6
7/**
8 * @author 爱做梦的锤子
9 * @create 2020/7/20
10 */
11public class ClusterLettuce {
12
13 private List<RedisURI> redisURIList;
14
15 /**
16 * 使用Lettuce连接集群模式redis
17 * @param redisURIList 集群中redis节点的信息,建议使用RedisURI.builder来进行构造
18 */
19 public ClusterLettuce(List<RedisURI> redisURIList) {
20 this.redisURIList = redisURIList;
21 }
22
23 /**
24 * 连接redis获取一个连接
25 * @return 一个redis的连接
26 */
27 public StatefulRedisClusterConnection<String, String> connect() {
28 RedisClusterClient redisClusterClient = RedisClusterClient.create(redisURIList);
29 StatefulRedisClusterConnection<String, String> connect = redisClusterClient.connect();
30 return connect;
31 }
32
33
34}
以上三段代码是使用Lettuce连接三种模式下Redis的简易演示代码,下面再附上测试类代码
测试类
1/**
2 * @author 爱做梦的锤子
3 * @create 2020/7/20
4 */
5public class LettuceTest {
6
7 private static final Logger LOGGER = LoggerFactory.getLogger(LettuceTest.class);
8 private static final String TEST_KEY = "lettuce";
9 private static final String TEST_VALUE = "dream-hammer";
10
11 @Test
12 public void SingleInstance(){
13 SingleInstanceLettuce singleInstanceLettuce = new SingleInstanceLettuce("192.168.56.90", 6379, "123456");
14 StatefulRedisConnection<String, String> connection = singleInstanceLettuce.connect();
15 RedisCommands<String, String> commands = connection.sync();
16 commands.set(TEST_KEY, TEST_VALUE);
17 LOGGER.info("lettuce单机单实例:{}",commands.get(TEST_KEY));
18 Assert.assertEquals(TEST_VALUE,commands.get(TEST_KEY));
19 }
20
21 @Test
22 public void sentinel(){
23 List<RedisURI> redisURIList = new ArrayList<>();
24 redisURIList.add(RedisURI.builder().withSentinelMasterId("redis-master").withSentinel("192.168.56.91",26379).withPassword("123456").build());
25 redisURIList.add(RedisURI.builder().withSentinelMasterId("redis-master").withSentinel("192.168.56.92",26379).withPassword("123456").build());
26 redisURIList.add(RedisURI.builder().withSentinelMasterId("redis-master").withSentinel("192.168.56.93",26379).withPassword("123456").build());
27 SentinelLettuce sentinelLettuce = new SentinelLettuce(redisURIList);
28 StatefulRedisMasterSlaveConnection<String, String> connection = sentinelLettuce.connect();
29 RedisCommands<String, String> commands = connection.sync();
30 commands.set(TEST_KEY, TEST_VALUE);
31 LOGGER.info("lettuce哨兵模式:{}",commands.get(TEST_KEY));
32 Assert.assertEquals(TEST_VALUE,commands.get(TEST_KEY));
33 }
34
35 @Test
36 public void cluster(){
37 List<RedisURI> redisURIList = new ArrayList<>();
38 redisURIList.add(RedisURI.builder().withHost("192.168.56.81").withPort(6379).withPassword("123456").build());
39 redisURIList.add(RedisURI.builder().withHost("192.168.56.82").withPort(6379).withPassword("123456").build());
40 redisURIList.add(RedisURI.builder().withHost("192.168.56.83").withPort(6379).withPassword("123456").build());
41 redisURIList.add(RedisURI.builder().withHost("192.168.56.84").withPort(6379).withPassword("123456").build());
42 redisURIList.add(RedisURI.builder().withHost("192.168.56.85").withPort(6379).withPassword("123456").build());
43 redisURIList.add(RedisURI.builder().withHost("192.168.56.86").withPort(6379).withPassword("123456").build());
44 ClusterLettuce clusterLettuce = new ClusterLettuce(redisURIList);
45 StatefulRedisClusterConnection<String, String> connection = clusterLettuce.connect();
46 RedisAdvancedClusterCommands<String, String> commands = connection.sync();
47 commands.set(TEST_KEY, TEST_VALUE);
48 LOGGER.info("lettuce集群模式:{}",commands.get(TEST_KEY));
49 Assert.assertEquals(TEST_VALUE,commands.get(TEST_KEY));
50 }
51
52}
二、在SpringBoot中使用Redis
在上一部分我们演示了直接使用不同的redis客户端连接Redis,并进行简单操作,在这一部分,我们将演示一下,在SpringBoot如何连接三种模式的redis
pom依赖
1<dependency>
2 <groupId>org.springframework.boot</groupId>
3 <artifactId>spring-boot-starter-data-redis</artifactId>
4</dependency>
在application.yml文件中配置redis连接信息
1# 连接单机单实例版的redis配置
2spring:
3 redis:
4 host: 192.168.56.90
5 port: 6379
6 password: 123456
7 database: 0
8
9# 连接哨兵模式的redis配置
10spring:
11 redis:
12 sentinel:
13 master: redis-master
14 nodes: 192.168.56.91:26379,192.168.56.92:26379,192.168.56.92:26379
15 password: 123456
16
17# 连接集群模式redis配置
18spring:
19 redis:
20 cluster:
21 nodes: 192.168.56.81:6379,192.168.56.82:6379,192.168.56.83:6379,192.168.56.84:6379,192.168.56.85:6379,192.168.56.86:6379
22 password: 123456
使用演示代码
1/**
2 * @author 爱做梦的锤子
3 * @create 2020/7/20
4 */
5@Service("redisSpring")
6public class RedisSpring {
7
8 @Autowired
9 private RedisTemplate redisTemplate;
10
11 @Autowired
12 private StringRedisTemplate stringRedisTemplate;
13
14 public Object redisTemplateOperate(Object key, Object value) {
15 redisTemplate.opsForValue().set(key, value);
16 return redisTemplate.opsForValue().get(key);
17 }
18
19 public String stringRedisTemplateOperate(String key, String value) {
20 stringRedisTemplate.opsForValue().set(key, value);
21 return stringRedisTemplate.opsForValue().get(key);
22 }
23
24}
测试该功能的代码
1/**
2 * @author 爱做梦的锤子
3 * @create 2020/7/20
4 */
5@SpringBootTest(classes = Application.class)
6@RunWith(SpringRunner.class)
7@EnableAutoConfiguration
8public class SpringTest {
9
10 private static final Logger LOGGER = LoggerFactory.getLogger(SpringTest.class);
11
12 @Autowired
13 private RedisSpring redisSpring;
14
15 private static final String TEST_KEY = "spring";
16 private static final String TEST_VALUE = "dream-hammer";
17
18 @Test
19 public void test() {
20 Object value = redisSpring.redisTemplateOperate(TEST_KEY, TEST_VALUE);
21 LOGGER.info("redisTemplate:{}",value);
22 Assert.assertEquals(value,TEST_VALUE);
23 String s = redisSpring.stringRedisTemplateOperate(TEST_KEY, TEST_VALUE);
24 LOGGER.info("stringRedisTemplate:{}",s);
25 Assert.assertEquals(TEST_VALUE,s);
26 }
27
28}
总结
觉得不错就点个赞叭QAQ