大数据开发Redis高级特性(第四十三篇)

73 阅读5分钟

一、Redis Java代码使用

pom文件引入依赖
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>4.3.1</version>
</dependency>
不使用线程池的方式
package com.strivelearn.java.redis;
​
import redis.clients.jedis.DefaultJedisClientConfig;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisClientConfig;
import redis.clients.jedis.JedisFactory;
​
/**
 * @author strivelearn
 * @version RedisOp.java, 2022年12月11日
 */
public class RedisOp {
    public static void main(String[] args) {
        DefaultJedisClientConfig config = DefaultJedisClientConfig.builder()
                                                                  .password("xys6154@")
                                                                  .build();
        Jedis jedis = new Jedis("192.168.234.100", 6379, config);
        String set = jedis.set("student", "zhangsan");
        String student = jedis.get("student");
        System.out.println(student);
        jedis.close();
    }
}
使用线程池的方式
package com.strivelearn.java.redis;
​
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
​
/**
 * Redis连接池方式
 *
 * @author strivelearn
 * @version RedisPoolOp.java, 2022年12月11日
 */
public class RedisPoolOp {
    public static void main(String[] args) {
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        //连接池最大空闲连接数
        jedisPoolConfig.setMaxIdle(10);
        //连接池创建的最大连接数
        jedisPoolConfig.setMaxTotal(10);
        //创建链接的超时时间
        jedisPoolConfig.setMaxWaitMillis(2000);
        //表示从连接池中获取链接的时候会测试一下,是否可用,这样可以保证取出的连接都是可用的
        jedisPoolConfig.setTestOnBorrow(true);
        //获取jedis连接池
        JedisPool jedisPool = new JedisPool(jedisPoolConfig, "192.168.234.100", 6379);
        //从jedis连接池取出一个链接
        Jedis resource = jedisPool.getResource();
        String zhangsan = resource.get("student");
        System.out.println("student" + zhangsan);
        //1.如果jedis是直接创建的单链接,此时表示直接关闭这个链接
        //2.如果jedis是从连接池中获取的链接,此时会把这个链接返回给连接池
        jedisPool.close();
​
    }
}

二、封装Redis工具类

package com.strivelearn.java.redis;
​
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
​
/**
 * @author xys
 * @version RedisUtils.java, 2022年12月11日
 */
public class RedisUtils {
    //私有构造函数,禁止new操作
    private RedisUtils() {
    }
​
    private static JedisPool jedisPool = null;
​
    /**
     * 获取redis链接
     *
     * @return
     */
    public static synchronized Jedis getJedis() {
        if (jedisPool == null) {
            JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
            //连接池最大空闲连接数
            jedisPoolConfig.setMaxIdle(10);
            //连接池创建的最大连接数
            jedisPoolConfig.setMaxTotal(10);
            //创建链接的超时时间
            jedisPoolConfig.setMaxWaitMillis(2000);
            //表示从连接池中获取链接的时候会测试一下,是否可用,这样可以保证取出的连接都是可用的
            jedisPoolConfig.setTestOnBorrow(true);
            //获取jedis连接池
            jedisPool = new JedisPool(jedisPoolConfig, "192.168.234.100", 6379);
        }
        return jedisPool.getResource();
    }
​
    /**
     * 归还redis链接
     *
     * @param jedis
     */
    public static void returnResource(Jedis jedis) {
        jedis.close();
    }
}

二、Redis高级命令

2.1、expire 生成时间
命令格式解释
expireexpire key seconds设置key的过期时间(单位:秒)
ttlttl key获取key的剩余有效时间
persistpersist key取消key的过期时间
expireatexpireat key timestamp设置key在指定时间戳过期

image-20221226200259471

2.2、pipeline管道
  1. 针对批量操作数据或者批量初始化数据的时候使用,效率高
  2. Redis的pipeline功能在命令行中没有实现,在Java客户端(jedis)中可以使用的

Hadoop-Pipeline管道.drawio

管道的原理:相当于一次性交互多条语句,提升效率

package com.strivelearn.java.redis;
​
import redis.clients.jedis.Jedis;
​
/**
 * @author strivelearn
 * @version PipelineMain.java, 2022年12月26日
 */
public class PipelineMain {
    public static void main(String[] args) {
        Jedis jedis = RedisUtils.getJedis();
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 100000; i++) {
            jedis.set("test" + i, "value" + i);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("插入10w条数据,消耗时间:" + (endTime - startTime) / 1000 + "s");
    }
}

插入10w条数据,消耗时间:42s

Jedis jedis = RedisUtils.getJedis();
Pipeline pipelined = jedis.pipelined();
long startTime = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
    pipelined.set("test1" + i, "value2" + i);
}
long endTime = System.currentTimeMillis();
System.out.println("插入10w条数据,消耗时间:" + (endTime - startTime)  + "ms");

插入10w条数据,消耗209ms

三、Redis持久化

  1. Redis持久化简单理解就是把内存中的数据持久化到磁盘中可以保证Redis重启之后还能恢复之前的数据
  2. Redis支持两种持久化,可以单独使用或者组合使用
  3. RDB(默认方式)和AOF
3.1、RDB(Redis Database)

RDB持久化是通过快照完成,当符合一定条件时Redis会自动将内存中的所有数据执行快照操作并存储到硬盘上,默认存储在dump.rdb文件中

RDB的优点:
  1. 由于存储的有数据快照文件,恢复数据很方便
RDB的缺点
  1. 会丢失最后一次快照以后更改的所有数据
3.2、AOF(Append Only File)

AOF持久化是通过日志文件的方式,默认情况下没有开启,可以通过appendonly参数开启。存储在appendonly.aof文件中

四、Redis的安全策略

  1. 设置Redis密码,在redis.conf配置文件中,requirepass
  2. 禁用flushall。在redis.conf把flushall进行重命名 rename-command flushall ""

五、Redis监控命令-monitor

image-20221226215003674

六、Redis架构演进

6.1、主从复制
  1. Redis的复制功能支持多个数据库之间的数据同步
  2. 通过Redis的复制功能可以很好的实现数据库的读写分离提高服务器的负载能力。主数据库(Master)主要进行写操作,而从数据库(Slave)负责读操作
  3. 一个主数据库可以有多个从数据库,而一个从数据库只能有一个主数据库
存在的问题:

如果master节点挂了,从节点是无法自动切换为主节点的。

6.2、哨兵机制(Sentinel)
  1. 监控:Sentinel实时监控主服务器和从服务器运行状态
  2. 提醒:当被监控的某个Redis服务器出现问题时,Sentinel可以向系统管理员发送通知,也可以通过API向其他程序发送通知
  3. 自动故障转移:当一个主服务器不能正常工作时,Senitinel可以将一个从服务器升级为主服务器,并对其他从服务器进行配置,让它们使用新的主服务器
6.3、集群模式
  1. Redis集群是一个无中心的分布式Redis存储架构,可以在多个节点之间数据共享,解决了Redis高可用,可扩展等问题
  2. 一个Redis集群包含16384个哈希槽(hash slot),数据库中的每个数据都属于这个16384个哈希槽中的一个
  3. 集群使用公式CRC16(key)%16384来计算键key属于哪个槽,集群中的每一个节点负责维护一部分哈希槽
  4. 集群中的每个节点都有1个或者N个复制品,其中一个伪主节点其余的为从节点,如果主节点下线了,集群就会把这个主节点的一个从节点设置为新的主节点,继续工作
  5. 如果一个主节点和它所有的从节点都下线的话,集群就会通知工作了。