操作系統(tǒng):CentOS-7.8
Redis版本:6.0.5
SpringBoot 2.1.5.RELEASE
Java Version 1.8.0_231
本篇內(nèi)容主要演示在Java代碼中連接和使用Redis疟呐,對Redis不熟悉的朋友可以先看前兩篇《一起學(xué)習(xí)Redis基礎(chǔ)》和《一起學(xué)習(xí)Redis高可用》,本篇涉及到的代碼完整版github地址為:https://github.com/telundusiji/dream-hammer/tree/master/module-6
一望侈、使用Redis客戶端
Jedis、Redisson和Lettuce都是比較常用的支持連接Redis的客戶端季二,所以在這里我們主要演示這三種客戶端如何連接不同的redis模式的redis
1.Jedis
Jedis特點(diǎn)
比較經(jīng)典的Redis的Java客戶端撼班,對Redis的命令支持比較全面
比較輕量和簡潔洋只,對其進(jìn)行改造和集成比較方便
不支持異步划乖,方法調(diào)用都是同步的贬养,使用的阻塞IO
客戶端實(shí)例非線程安全,多線程并發(fā)場景下琴庵,需要通過連接池來使用客戶端
早期版本Spring的默認(rèn)客戶端
使用演示
- pom依賴
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.3</version>
</dependency>
- Jedis連接單機(jī)單實(shí)例Redis
import redis.clients.jedis.Jedis;
/**
* @author 愛做夢的錘子
* @create 2020/7/17
*/
public class SingleInstanceJedis {
private String host;
private Integer port;
private String password;
/**
* 連接單機(jī)單實(shí)例的redis
*
* @param host redis主機(jī)地址
* @param port redis服務(wù)端口
* @param password redis認(rèn)證密碼
*/
public SingleInstanceJedis(String host, Integer port, String password) {
this.host = host;
this.port = port;
this.password = password;
}
/**
* 連接redis
*
* @return 一個(gè)Jedis客戶端
*/
public Jedis connect() {
Jedis jedis = new Jedis(host, port);
jedis.auth(password);
return jedis;
}
}
- Jedis連接哨兵模式Redis
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisSentinelPool;
import java.util.Set;
/**
* @author 愛做夢的錘子
* @create 2020/7/17
*/
public class SentinelJedis {
private JedisSentinelPool jedisSentinelPool;
/**
* 連接哨兵模式的redis
*
* @param masterName redis的master名稱
* @param sentinels 哨兵的主機(jī)和端口信息
* @param password redis的認(rèn)證密碼
*/
public SentinelJedis(String masterName, Set<String> sentinels, String password) {
//根據(jù)redis的信息創(chuàng)建一個(gè)redis哨兵的連接池
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(10);
config.setMaxIdle(5);
config.setMinIdle(5);
jedisSentinelPool = new JedisSentinelPool(masterName, sentinels, config, password);
}
/**
* 從連接池中取出一個(gè)客戶端
*
* @return 獲取一個(gè)Jedis客戶端
*/
public Jedis connect() {
return jedisSentinelPool.getResource();
}
/**
* 銷毀連接池
*/
public void close() {
jedisSentinelPool.close();
jedisSentinelPool.destroy();
}
}
- Jedis連接集群模式Redis
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
import java.util.Set;
/**
* @author 愛做夢的錘子
* @create 2020/7/17
*/
public class ClusterJedis {
private Set<HostAndPort> redisNodes;
private String password;
private GenericObjectPoolConfig config;
/**
* 連接redis cluster
*
* @param redisNodes 集群中redis節(jié)點(diǎn)信息
* @param password redis 密碼
*/
public ClusterJedis(Set<HostAndPort> redisNodes, String password) {
this.redisNodes = redisNodes;
this.password = password;
config = new GenericObjectPoolConfig();
config.setMaxTotal(10);
config.setMaxIdle(5);
config.setMinIdle(5);
}
/**
* 連接redis cluster
*
* @return 一個(gè)redis cluster客戶端
*/
public JedisCluster connect() {
JedisCluster jedisCluster = new JedisCluster(redisNodes, 10000, 10000, 3, password, config);
return jedisCluster;
}
}
以上三段代碼是使用Jedis連接三種模式下Redis的簡易演示代碼误算,下面再附上測試類代碼
- 測試類
/**
* @author 愛做夢的錘子
* @create 2020/7/17
*/
public class JedisTest {
private static final Logger LOGGER = LoggerFactory.getLogger(JedisTest.class);
private static final String TEST_KEY = "jedis";
private static final String TEST_VALUE = "dream-hammer";
@Test
public void singleInstance() {
SingleInstanceJedis singleInstanceJedis = new SingleInstanceJedis("192.168.56.90", 6379, "123456");
Jedis jedis = singleInstanceJedis.connect();
jedis.set(TEST_KEY, TEST_VALUE);
LOGGER.info("jedis單機(jī)單實(shí)例:{}", jedis.get(TEST_KEY));
Assert.assertEquals(TEST_VALUE, jedis.get(TEST_KEY));
}
@Test
public void sentinel() {
Set<String> sentinels = new HashSet<>();
sentinels.add("192.168.56.91:26379");
sentinels.add("192.168.56.92:26379");
sentinels.add("192.168.56.93:26379");
SentinelJedis sentinelJedis = new SentinelJedis("redis-master", sentinels, "123456");
Jedis jedis = sentinelJedis.connect();
jedis.set(TEST_KEY, TEST_VALUE);
LOGGER.info("jedis哨兵模式:{}", jedis.get(TEST_KEY));
Assert.assertEquals(TEST_VALUE, jedis.get(TEST_KEY));
}
@Test
public void cluster() {
Set<HostAndPort> redisNodes = new HashSet<>();
redisNodes.add(new HostAndPort("192.168.56.81",6379));
redisNodes.add(new HostAndPort("192.168.56.82",6379));
redisNodes.add(new HostAndPort("192.168.56.83",6379));
redisNodes.add(new HostAndPort("192.168.56.84",6379));
redisNodes.add(new HostAndPort("192.168.56.85",6379));
redisNodes.add(new HostAndPort("192.168.56.86",6379));
ClusterJedis clusterJedis = new ClusterJedis(redisNodes, "123456");
JedisCluster jedisCluster = clusterJedis.connect();
jedisCluster.set(TEST_KEY, TEST_VALUE);
LOGGER.info("jedis集群模式:{}", jedisCluster.get(TEST_KEY));
Assert.assertEquals(TEST_VALUE, jedisCluster.get(TEST_KEY));
}
}
2.Redisson
Redisson特點(diǎn)
基于Netty實(shí)現(xiàn),使用非阻塞IO迷殿,支持異步儿礼,性能高
API是線程安全的,可以操作單個(gè)Redisson連接來完成多種操作
實(shí)現(xiàn)多種分布式和可擴(kuò)展的Java數(shù)據(jù)結(jié)構(gòu)庆寺,例如蚊夫,分布式鎖,分布式集合懦尝,可通過Redis支持延遲隊(duì)列
Redisson注重分布式和鎖的相關(guān)功能知纷,所以在基礎(chǔ)功能上較為簡單,不支持Redis的原生命令操作陵霉,比如不支持字符串操作等
使用演示
- pom依賴
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.12.5</version>
</dependency>
- redisson連接單機(jī)單實(shí)例Redis
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
/**
* @author 愛做夢的錘子
* @create 2020/7/17
*/
public class SingleInstanceRedisson {
private Config config;
/**
* 連接單機(jī)單實(shí)例的redis
*
* @param host redis主機(jī)地址
* @param port redis 端口
* @param password redis密碼
*/
public SingleInstanceRedisson(String host, Integer port, String password) {
config = new Config();
config.useSingleServer()
.setAddress("redis://" + host + ":" + port)
.setPassword(password);
}
/**
* 連接redis
*
* @return 一個(gè)RedissonClient客戶端
*/
public RedissonClient connect() {
RedissonClient redissonClient = Redisson.create(config);
return redissonClient;
}
}
- redisson連接哨兵模式Redis
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
/**
* @author 愛做夢的錘子
* @create 2020/7/17
*/
public class SentinelRedisson {
private Config config;
/**
* 連接哨兵模式redis
*
* @param masterName redis的master名稱
* @param sentinels 哨兵的連接信息 redis://sentinelHost:sentinelPort
* @param password redis密碼
*/
public SentinelRedisson(String masterName, String[] sentinels, String password) {
config = new Config();
config.useSentinelServers()
.setMasterName(masterName)
.addSentinelAddress(sentinels)
.setPassword(password);
}
/**
* 連接redis
*
* @return 一個(gè)RedissonClient客戶端
*/
public RedissonClient connect() {
RedissonClient redissonClient = Redisson.create(config);
return redissonClient;
}
}
- redisson連接集群模式Redis
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
/**
* @author 愛做夢的錘子
* @create 2020/7/17
*/
public class ClusterRedisson {
private Config config;
/**
* 連接cluster模式的redis
*
* @param redisNodes redis集群中節(jié)點(diǎn)信息 redis://nodeHost:nodePort
* @param password redis密碼
*/
public ClusterRedisson(String[] redisNodes, String password) {
config = new Config();
config.useClusterServers()
.addNodeAddress(redisNodes)
.setPassword(password);
}
/**
* 連接redis
*
* @return 一個(gè)RedissonClient客戶端
*/
public RedissonClient connect() {
RedissonClient redissonClient = Redisson.create(config);
return redissonClient;
}
}
以上三段代碼是使用Redisson連接三種模式下Redis的簡易演示代碼琅轧,下面再附上測試類代碼
- 測試類
/**
* @author 愛做夢的錘子
* @create 2020/7/20
*/
public class RedissonTest {
private static final Logger LOGGER = LoggerFactory.getLogger(RedissonTest.class);
private static final String TEST_KEY = "redisson";
private static final long TEST_VALUE = 100L;
@Test
public void singleInstance() {
SingleInstanceRedisson singleInstanceRedisson = new SingleInstanceRedisson("192.168.56.90", 6379, "123456");
RedissonClient redissonClient = singleInstanceRedisson.connect();
RAtomicLong atomicLong = redissonClient.getAtomicLong(TEST_KEY);
atomicLong.set(TEST_VALUE);
LOGGER.info("redisson單機(jī)單實(shí)例:{}", redissonClient.getAtomicLong(TEST_KEY).get());
Assert.assertEquals(TEST_VALUE, redissonClient.getAtomicLong(TEST_KEY).get());
}
@Test
public void sentinel() {
String[] sentinels = new String[]{"redis://192.168.56.91:26379", "redis://192.168.56.92:26379", "redis://192.168.56.93:26379"};
SentinelRedisson sentinelRedisson = new SentinelRedisson("redis-master", sentinels, "123456");
RedissonClient redissonClient = sentinelRedisson.connect();
RAtomicLong atomicLong = redissonClient.getAtomicLong(TEST_KEY);
atomicLong.set(TEST_VALUE);
LOGGER.info("redisson哨兵模式:{}", redissonClient.getAtomicLong(TEST_KEY).get());
Assert.assertEquals(TEST_VALUE, redissonClient.getAtomicLong(TEST_KEY).get());
}
@Test
public void cluster() {
String[] redisNodes = new String[]{
"redis://192.168.56.81:6379",
"redis://192.168.56.82:6379",
"redis://192.168.56.83:6379",
"redis://192.168.56.84:6379",
"redis://192.168.56.85:6379",
"redis://192.168.56.86:6379"
};
ClusterRedisson clusterRedisson = new ClusterRedisson(redisNodes, "123456");
RedissonClient redissonClient = clusterRedisson.connect();
RAtomicLong atomicLong = redissonClient.getAtomicLong(TEST_KEY);
atomicLong.set(TEST_VALUE);
LOGGER.info("redisson集群模式:{}", redissonClient.getAtomicLong(TEST_KEY).get());
Assert.assertEquals(TEST_VALUE, redissonClient.getAtomicLong(TEST_KEY).get());
}
}
3.Lettuce
Lettuce特點(diǎn)
Redis高級客戶端,線程安全的踊挠,單個(gè)Lettuce連接可以在多個(gè)線程中操作
基于Netty實(shí)現(xiàn)乍桂,使用非阻塞IO,支持異步
對Redis基礎(chǔ)操作支持全面效床,相對Jedis來說更加高效睹酌,不要考慮太多線程安全問題
相對Redisson來說分布式鎖和分布式數(shù)據(jù)結(jié)構(gòu)等都需要自行實(shí)現(xiàn)
Spring現(xiàn)有版本的默認(rèn)redis客戶端
使用演示
- pom依賴
<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
- lettuce連接單機(jī)單實(shí)例Redis
import io.lettuce.core.RedisClient;
import io.lettuce.core.RedisURI;
import io.lettuce.core.api.StatefulRedisConnection;
/**
* @author 愛做夢的錘子
* @create 2020/7/20
*/
public class SingleInstanceLettuce {
private RedisURI redisURI;
/**
* 使用Lettuce連接單機(jī)單實(shí)例的redis
* @param host redis的主機(jī)地址
* @param port redis的端口號
* @param password redis的密碼
*/
public SingleInstanceLettuce(String host, Integer port, String password) {
redisURI = RedisURI.builder()
.withHost(host)
.withPort(port)
.withPassword(password)
.build();
}
/**
* 連接redis獲取一個(gè)連接
* @return 一個(gè)redis連接
*/
public StatefulRedisConnection<String, String> connect() {
RedisClient redisClient = RedisClient.create(redisURI);
StatefulRedisConnection<String, String> connect = redisClient.connect();
return connect;
}
}
- lettuce連接哨兵模式redis
import io.lettuce.core.RedisClient;
import io.lettuce.core.RedisURI;
import io.lettuce.core.codec.Utf8StringCodec;
import io.lettuce.core.masterslave.MasterSlave;
import io.lettuce.core.masterslave.StatefulRedisMasterSlaveConnection;
import java.util.List;
/**
* @author 愛做夢的錘子
* @create 2020/7/20
*/
public class SentinelLettuce {
private List<RedisURI> redisURIList;
/**
* 連接哨兵模式的redis
* @param redisURIList 哨兵模式redis下的哨兵的信息,建議使用RedisURI.builder.sentinel填寫哨兵信息來進(jìn)行構(gòu)造
*/
public SentinelLettuce(List<RedisURI> redisURIList) {
this.redisURIList = redisURIList;
}
/**
* 連接redis獲取一個(gè)連接
* @return 一個(gè)redis的連接
*/
public StatefulRedisMasterSlaveConnection<String, String> connect() {
RedisClient redisClient = RedisClient.create();
StatefulRedisMasterSlaveConnection<String, String> connect = MasterSlave.connect(redisClient, new Utf8StringCodec(), redisURIList);
return connect;
}
}
- lettuce連接集群模式Redis
import io.lettuce.core.RedisURI;
import io.lettuce.core.cluster.RedisClusterClient;
import io.lettuce.core.cluster.api.StatefulRedisClusterConnection;
import java.util.List;
/**
* @author 愛做夢的錘子
* @create 2020/7/20
*/
public class ClusterLettuce {
private List<RedisURI> redisURIList;
/**
* 使用Lettuce連接集群模式redis
* @param redisURIList 集群中redis節(jié)點(diǎn)的信息剩檀,建議使用RedisURI.builder來進(jìn)行構(gòu)造
*/
public ClusterLettuce(List<RedisURI> redisURIList) {
this.redisURIList = redisURIList;
}
/**
* 連接redis獲取一個(gè)連接
* @return 一個(gè)redis的連接
*/
public StatefulRedisClusterConnection<String, String> connect() {
RedisClusterClient redisClusterClient = RedisClusterClient.create(redisURIList);
StatefulRedisClusterConnection<String, String> connect = redisClusterClient.connect();
return connect;
}
}
以上三段代碼是使用Lettuce連接三種模式下Redis的簡易演示代碼憋沿,下面再附上測試類代碼
- 測試類
/**
* @author 愛做夢的錘子
* @create 2020/7/20
*/
public class LettuceTest {
private static final Logger LOGGER = LoggerFactory.getLogger(LettuceTest.class);
private static final String TEST_KEY = "lettuce";
private static final String TEST_VALUE = "dream-hammer";
@Test
public void SingleInstance(){
SingleInstanceLettuce singleInstanceLettuce = new SingleInstanceLettuce("192.168.56.90", 6379, "123456");
StatefulRedisConnection<String, String> connection = singleInstanceLettuce.connect();
RedisCommands<String, String> commands = connection.sync();
commands.set(TEST_KEY, TEST_VALUE);
LOGGER.info("lettuce單機(jī)單實(shí)例:{}",commands.get(TEST_KEY));
Assert.assertEquals(TEST_VALUE,commands.get(TEST_KEY));
}
@Test
public void sentinel(){
List<RedisURI> redisURIList = new ArrayList<>();
redisURIList.add(RedisURI.builder().withSentinelMasterId("redis-master").withSentinel("192.168.56.91",26379).withPassword("123456").build());
redisURIList.add(RedisURI.builder().withSentinelMasterId("redis-master").withSentinel("192.168.56.92",26379).withPassword("123456").build());
redisURIList.add(RedisURI.builder().withSentinelMasterId("redis-master").withSentinel("192.168.56.93",26379).withPassword("123456").build());
SentinelLettuce sentinelLettuce = new SentinelLettuce(redisURIList);
StatefulRedisMasterSlaveConnection<String, String> connection = sentinelLettuce.connect();
RedisCommands<String, String> commands = connection.sync();
commands.set(TEST_KEY, TEST_VALUE);
LOGGER.info("lettuce哨兵模式:{}",commands.get(TEST_KEY));
Assert.assertEquals(TEST_VALUE,commands.get(TEST_KEY));
}
@Test
public void cluster(){
List<RedisURI> redisURIList = new ArrayList<>();
redisURIList.add(RedisURI.builder().withHost("192.168.56.81").withPort(6379).withPassword("123456").build());
redisURIList.add(RedisURI.builder().withHost("192.168.56.82").withPort(6379).withPassword("123456").build());
redisURIList.add(RedisURI.builder().withHost("192.168.56.83").withPort(6379).withPassword("123456").build());
redisURIList.add(RedisURI.builder().withHost("192.168.56.84").withPort(6379).withPassword("123456").build());
redisURIList.add(RedisURI.builder().withHost("192.168.56.85").withPort(6379).withPassword("123456").build());
redisURIList.add(RedisURI.builder().withHost("192.168.56.86").withPort(6379).withPassword("123456").build());
ClusterLettuce clusterLettuce = new ClusterLettuce(redisURIList);
StatefulRedisClusterConnection<String, String> connection = clusterLettuce.connect();
RedisAdvancedClusterCommands<String, String> commands = connection.sync();
commands.set(TEST_KEY, TEST_VALUE);
LOGGER.info("lettuce集群模式:{}",commands.get(TEST_KEY));
Assert.assertEquals(TEST_VALUE,commands.get(TEST_KEY));
}
}
二、在SpringBoot中使用Redis
在上一部分我們演示了直接使用不同的redis客戶端連接Redis沪猴,并進(jìn)行簡單操作卤妒,在這一部分,我們將演示一下字币,在SpringBoot如何連接三種模式的redis
- pom依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
- 在application.yml文件中配置redis連接信息
# 連接單機(jī)單實(shí)例版的redis配置
spring:
redis:
host: 192.168.56.90
port: 6379
password: 123456
database: 0
# 連接哨兵模式的redis配置
spring:
redis:
sentinel:
master: redis-master
nodes: 192.168.56.91:26379,192.168.56.92:26379,192.168.56.92:26379
password: 123456
# 連接集群模式redis配置
spring:
redis:
cluster:
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
password: 123456
- 使用演示代碼
/**
* @author 愛做夢的錘子
* @create 2020/7/20
*/
@Service("redisSpring")
public class RedisSpring {
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private StringRedisTemplate stringRedisTemplate;
public Object redisTemplateOperate(Object key, Object value) {
redisTemplate.opsForValue().set(key, value);
return redisTemplate.opsForValue().get(key);
}
public String stringRedisTemplateOperate(String key, String value) {
stringRedisTemplate.opsForValue().set(key, value);
return stringRedisTemplate.opsForValue().get(key);
}
}
- 測試該功能的代碼
/**
* @author 愛做夢的錘子
* @create 2020/7/20
*/
@SpringBootTest(classes = Application.class)
@RunWith(SpringRunner.class)
@EnableAutoConfiguration
public class SpringTest {
private static final Logger LOGGER = LoggerFactory.getLogger(SpringTest.class);
@Autowired
private RedisSpring redisSpring;
private static final String TEST_KEY = "spring";
private static final String TEST_VALUE = "dream-hammer";
@Test
public void test() {
Object value = redisSpring.redisTemplateOperate(TEST_KEY, TEST_VALUE);
LOGGER.info("redisTemplate:{}",value);
Assert.assertEquals(value,TEST_VALUE);
String s = redisSpring.stringRedisTemplateOperate(TEST_KEY, TEST_VALUE);
LOGGER.info("stringRedisTemplate:{}",s);
Assert.assertEquals(TEST_VALUE,s);
}
}
總結(jié)
在本篇中主要是代碼演示则披,演示三種客戶端連接三種模式下的redis的方式,可以幫助大家快速學(xué)習(xí)和使用redis洗出。由于本篇代碼比較多士复,所以代碼錘子也傳到了github地址為:https://github.com/telundusiji/dream-hammer/tree/master/module-6
個(gè)人公眾號【愛做夢的錘子】,全網(wǎng)同id,個(gè)站 http://te-amo.site阱洪,歡迎關(guān)注便贵,里面會分享更多有用知識
覺得不錯就點(diǎn)個(gè)贊叭QAQ