一起学习Redis之在Java中使用

操作系统:CentOS-7.8
Redis版本:6.0.5
SpringBoot 2.1.5.RELEASE
Java Version 1.8.0_231

本篇内容主要演示在Java代码中连接和使用Redis,对Redis不熟悉的朋友可以先看前两篇《一起学习Redis基础》和《一起学习Redis高可用》,本篇涉及到的代码完整版github地址为:https://github.com/telundusiji/dream-hammer/tree/master/module-6

一、使用Redis客户端

Jedis、Redisson和Lettuce都是比较常用的支持连接Redis的客户端,所以在这里我们主要演示这三种客户端如何连接不同的redis模式的redis

1.Jedis

Jedis特点

  • 比较经典的Redis的Java客户端,对Redis的命令支持比较全面

  • 比较轻量和简洁,对其进行改造和集成比较方便

  • 不支持异步,方法调用都是同步的,使用的阻塞IO

  • 客户端实例非线程安全,多线程并发场景下,需要通过连接池来使用客户端

  • 早期版本Spring的默认客户端

使用演示

  • pom依赖

<dependency>
	<groupId>redis.clientsgroupId>
	<artifactId>jedisartifactId>
	<version>2.9.3version>
dependency>

  • Jedis连接单机单实例Redis

import redis.clients.jedis.Jedis;

/**
 * @author 爱做梦的锤子
 * @create 2020/7/17
 */
public class SingleInstanceJedis {


    private String host;
    private Integer port;
    private String password;

    /**
     * 连接单机单实例的redis
     *
     * @param host     redis主机地址
     * @param port     redis服务端口
     * @param password redis认证密码
     */
    public SingleInstanceJedis(String host, Integer port, String password) {
        this.host = host;
        this.port = port;
        this.password = password;
    }

    /**
     * 连接redis
     *
     * @return 一个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  哨兵的主机和端口信息
     * @param password   redis的认证密码
     */
    public SentinelJedis(String masterName, Set<String> sentinels, String password) {
        //根据redis的信息创建一个redis哨兵的连接池
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(10);
        config.setMaxIdle(5);
        config.setMinIdle(5);
        jedisSentinelPool = new JedisSentinelPool(masterName, sentinels, config, password);
    }

    /**
     * 从连接池中取出一个客户端
     *
     * @return 获取一个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节点信息
     * @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 一个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单机单实例:{}", 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特点

  • 基于Netty实现,使用非阻塞IO,支持异步,性能高

  • API是线程安全的,可以操作单个Redisson连接来完成多种操作

  • 实现多种分布式和可扩展的Java数据结构,例如,分布式锁,分布式集合,可通过Redis支持延迟队列

  • Redisson注重分布式和锁的相关功能,所以在基础功能上较为简单,不支持Redis的原生命令操作,比如不支持字符串操作等

使用演示

  • pom依赖

<dependency>
    <groupId>org.redissongroupId>
    <artifactId>redissonartifactId>
    <version>3.12.5version>
dependency>

  • redisson连接单机单实例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;

    /**
     * 连接单机单实例的redis
     *
     * @param host     redis主机地址
     * @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 一个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 一个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集群中节点信息 redis://nodeHost:nodePort
     * @param password   redis密码
     */
    public ClusterRedisson(String[] redisNodes, String password) {
        config = new Config();
        config.useClusterServers()
                .addNodeAddress(redisNodes)
                .setPassword(password);

    }

    /**
     * 连接redis
     *
     * @return 一个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单机单实例:{}", 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特点

  • Redis高级客户端,线程安全的,单个Lettuce连接可以在多个线程中操作

  • 基于Netty实现,使用非阻塞IO,支持异步

  • 对Redis基础操作支持全面,相对Jedis来说更加高效,不要考虑太多线程安全问题

  • 相对Redisson来说分布式锁和分布式数据结构等都需要自行实现

  • Spring现有版本的默认redis客户端

使用演示

  • pom依赖

<dependency>
    <groupId>io.lettucegroupId>
    <artifactId>lettuce-coreartifactId>
    <version>5.1.6.RELEASEversion>
dependency>

  • lettuce连接单机单实例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连接单机单实例的redis
     * @param host redis的主机地址
     * @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获取一个连接
     * @return 一个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填写哨兵信息来进行构造
     */
    public SentinelLettuce(List<RedisURI> redisURIList) {
        this.redisURIList = redisURIList;
    }

    /**
     * 连接redis获取一个连接
     * @return 一个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节点的信息,建议使用RedisURI.builder来进行构造
     */
    public ClusterLettuce(List<RedisURI> redisURIList) {
        this.redisURIList = redisURIList;
    }

    /**
     * 连接redis获取一个连接
     * @return 一个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单机单实例:{}",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,并进行简单操作,在这一部分,我们将演示一下,在SpringBoot如何连接三种模式的redis

  • pom依赖

<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-data-redisartifactId>
dependency>

  • 在application.yml文件中配置redis连接信息

# 连接单机单实例版的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);
    }

}

总结

在本篇中主要是代码演示,演示三种客户端连接三种模式下的redis的方式,可以帮助大家快速学习和使用redis。由于本篇代码比较多,所以代码锤子也传到了github地址为:https://github.com/telundusiji/dream-hammer/tree/master/module-6

个人公众号【爱做梦的锤子】,全网同id,个站 http://te-amo.site,欢迎关注,里面会分享更多有用知识

觉得不错就点个赞叭QAQ

你可能感兴趣的:(redis,java)