Redis的事务,持久化,主从,哨兵,集群以及常见问题

Redis

Redis的AUTH

# 设置Redis连接密码
requirepass 密码

后期部署Redis上线时必定要设置密码

  • 在redis.conf配置文件中追加一个属性 requirepass 密码
  • 在Redis启动后,在容器中的redis-cli中执行config set requirepass 密码(重启后无效,基本不用)
    客户端连接时,如何指定密码:
  • redis-cli中,采用auth命令,在执行读写操作前,先执行auth密码
  • 图形化界面直接连接验证
  • java操作时:
    • 单独在执行的Jedis的方法前,先执行jedis.auth(密码)
    • 在使用JedisPool时,在构造方法中,追加密码操作即可。

Redis的事务

Redis的事务不同于传统的关系型数据库的事务

  • 一次Redis的事务操作,该成功的成功,该失败的失败。
  • Redis的事务和watch监听机制配合使用:先执行watch指定监听的key,如果在一次事务操作中,监听的key被修改了,当前事务自动取消。
  • 使用命令:
    • mutli:开启事务
    • exec:执行事务
    • discard:取消事务
    • watch key [key…]:监听指定的key
    • unwatch:取消全部监听的key

Redis的持久化机制

在/usr/local/docker_redis/conf/redis.conf文件中

# 开启RDB持久化,指定持久化文件存放的路径
dir /data/
dbfilename redis.rdb
# 指定Redis的RDB持久化时机
save 10 1
#----------------------------------------------
# 开启AOF持久化
appendonly yes
# 指定AOF文件的名称
appendfilename "redis.aof"
# 指定AOF持久化时机
appendfsync everysec
RDB:
  • 基于二进制文件持久化数据,存储速度块,占用空间小,传输速度块,恢复数据速度块。
  • 持久化时机:
    • 在指定时间内,执行了多少次写操作,就执行RDB持久化。
    • after 900 sec (15 min) if at least 1 key changed
    • save 900 1
  • RDB持久化机制相对不安全,可能会丢失数据。

AOF:

  • 基于日志文件持久化数据,数据更安全不易丢失,日志文件可以看懂。
  • 持久化时机:
    • 每执行一次命令就执行AOF持久化:appendfsync always
    • 每秒执行一次AOF持久化:appendfsync sec (默认的,也是推荐的)
    • 根据系统环境,一段时间执行一次,不可控:appendfsync no
  • AOF文件在内容特别多时,恢复数据速度相对RDB更慢,而且占用空间大。
    RDB和AOF的注意事项
  • Redis官方推荐同时开启RDB和AOF,不但保证数据的安全,也可以提升数据传输,恢复等等的效率。
  • 如果同时开启了RDB和AOF,在恢复数据时,优先使用AOF文件。
  • 如果同时开启了RDB和AOF,在RDB执行持久化时,RDB文件会被AOF文件覆盖掉。

Redis 的主从架构

主从架构可以帮助我们提升Redis读取数据的能力,通过搭建多个slave从节点,来提升读写瓶颈。

  • 主节点可以进行读写操作,从节点只能执行读操作。
  • 从节点不会相互通讯,只连接Master主节点。
  • 从节点的数据都是从master同步过来的。
  • 如果主从架构中matser节点宕机,整个Redis服务将不提供写操作。

实现主从架构配置:

  • 只需要让Slave从节点链接上Master集合。
  • 在/usr/local/docker_redis_master-slave/conf中加入 replicaof masterip masterport

Redis的主从+哨兵

由于主从架构存在单点故障问题,当Master节点宕机后,主从架构将无法提供写操作,可以在主从架构的基础上,添加哨兵,在Master宕机后,哨兵可以在多个Slave中选举出以为全新的Master节点。

  • 准备sentinel配置文件:
    • 守护进程,保证哨兵可以后台启动:daemonize yes
    • 告诉哨兵Master节点信息:sentinel monitor mymaster redis1 6379 2
      指定哨兵多久检测一下,主从架构的健康情况:sentinel down-after-milliseconds mymaster 10000
      -正常的启动Redis的主从架构容器
  • 分别的进入Master和Slave容器,并分别启动哨兵redis-sentinel sentinel1.conf,指定编写好的配置文件
    修改Redis服务的配置文件权限:chmod -R 777 conf
  • 直接关闭Master容器,查看slave节点的日志:CONFIG REWRITE …
  • 发现Redis的配置文件全部被哨兵重写。

Redis集群

Redis集群介绍

主从+哨兵的架构,无法提升存储数据能力的上限,也无法分担写数据的压力。而Redis集群时可以做到的。

  • Redis集群是无中心的。
  • 每一个Redis节点之间有一个ping-pang机制,每个节点之间都可以相互通讯。
  • 由于Redis集群带有投票机制,集群的节点树应该时奇数个。
  • Redis集群中默认分配16384个哈希槽,并且由不同的Redis节点去维护,当客户端写数据时,会先将key进行crc16运算,并且将最终得到的结果对16384取余数,得到的结果是0~16383之间的数字,直接根据结果存储到不同的Redis节点,从而提升存储能力,以及分担写数据的压力。
  • 每个Redis集群中的节点,至少要由一个从节点,避免单点故障。
  • 集群中的从节点,不会分担读数据的压力,想提升读数据的能力,需要单独自己搭建主从。
  • 在Redis集群超过半数节点不可用时,集群才会瘫痪。
搭建Redis集群

1、准备6个Redis的服务

version: "3.1"
services:
  redis1:
    image: 10.0.134.175:5000/redis:5.0.9
    restart: always
    container_name: redis1
    environment:
      - TZ=Asia/Shanghai
    ports:
      - 7001:7001
      - 17001:17001
    volumes:
      - ./conf/redis1.conf:/usr/local/redis/redis.conf
    command: ["redis-server","/usr/local/redis/redis.conf"]
  redis2:
    image: 10.0.134.175:5000/redis:5.0.9
    restart: always
    container_name: redis2
    environment:
      - TZ=Asia/Shanghai
    ports:
      - 7002:7002
      - 17002:17002
    volumes:
      - ./conf/redis2.conf:/usr/local/redis/redis.conf
    command: ["redis-server","/usr/local/redis/redis.conf"]  
  redis3:
    image: 10.0.134.175:5000/redis:5.0.9
    restart: always
    container_name: redis3
    environment:
      - TZ=Asia/Shanghai
    ports:
      - 7003:7003
      - 17003:17003
    volumes:
      - ./conf/redis3.conf:/usr/local/redis/redis.conf
    command: ["redis-server","/usr/local/redis/redis.conf"]  
  redis4:
    image: 10.0.134.175:5000/redis:5.0.9
    restart: always
    container_name: redis4
    environment:
      - TZ=Asia/Shanghai
    ports:
      - 7004:7004
      - 17004:17004
    volumes:
      - ./conf/redis4.conf:/usr/local/redis/redis.conf
    command: ["redis-server","/usr/local/redis/redis.conf"]  
  redis5:
    image: 10.0.134.175:5000/redis:5.0.9
    restart: always
    container_name: redis5
    environment:
      - TZ=Asia/Shanghai
    ports:
      - 7005:7005
      - 17005:17005
    volumes:
      - ./conf/redis5.conf:/usr/local/redis/redis.conf
    command: ["redis-server","/usr/local/redis/redis.conf"]  
  redis6:
    image: 10.0.134.175:5000/redis:5.0.9
    restart: always
    container_name: redis6
    environment:
      - TZ=Asia/Shanghai
    ports:
      - 7006:7006
      - 17006:17006
    volumes:
      - ./conf/redis6.conf:/usr/local/redis/redis.conf
    command: ["redis-server","/usr/local/redis/redis.conf"]  

2、准备6个Redis的配置文件

# 0. 指定端口号
port 7001
# 1. 开启Redis集群。  832行。
cluster-enabled yes
# 2. 指定Redis集群节点信息的文件名称  840行。
cluster-config-file nodes-6379.conf
# 3. Docker搭建Redis集群,指定 ip,port,bus
cluster-announce-ip 10.0.131.232
cluster-announce-port 7001
cluster-announce-bus-port 17001
.....

3、启动6个Redis服务
4、进入到任意一个Redis服务的容器中,执行命令

redis-cli --cluster create ip1:port1 ip2:port2 ip3:port3 ip4:port4 ip5:port5 ip6:port6 --cluster-repalicas 1

5、集群启动成功后,使用redis-cli连接

redis-cli -p 端口号 -c

Java连接Redis集群

@Test
// Keys操作,在原生的JedisCluster中,无法使用,需要自己封装.
public void test(){
    Set<HostAndPort> nodes = new HashSet<>();
    HostAndPort h1 = new HostAndPort("10.0.131.232",7001);
    HostAndPort h2 = new HostAndPort("10.0.131.232",7002);
    HostAndPort h3 = new HostAndPort("10.0.131.232",7003);
    HostAndPort h4 = new HostAndPort("10.0.131.232",7004);
    HostAndPort h5 = new HostAndPort("10.0.131.232",7005);
    HostAndPort h6 = new HostAndPort("10.0.131.232",7006);
    nodes.add(h1);
    nodes.add(h2);
    nodes.add(h3);
    nodes.add(h4);
    nodes.add(h5);
    nodes.add(h6);

    JedisCluster jedisCluster = new JedisCluster(nodes);

    Map<String, JedisPool> clusterNodes = jedisCluster.getClusterNodes();

    Set<Map.Entry<String, JedisPool>> entries = clusterNodes.entrySet();

    Set<String> allKeys = new HashSet<>();

    for (Map.Entry<String, JedisPool> entry : entries) {
        JedisPool pool = entry.getValue();
        Jedis jedis = pool.getResource();
        Set<String> keys = jedis.keys("*");
        allKeys.addAll(keys);
    }

    System.out.println(allKeys);
}

Redis常见问题(重点|面试题)

删除策略
  • 定期删除,默认在100ms中,随机抽取出三个设置了生存时间的key,如果生存时间已经到了,会删除当前key。
  • 惰性删除,在你查询一个key时,先查看当前key的生存时间是否已经到了,如果到了,直接删除当前key,并给用户返回一个null。
淘汰策略
  • volatile-lru:在设置了过期时间的key中,删除最近最少使用的key。
  • allkeys-lru:在全部的key中,删除最近最少使用的key。
  • volatile-lfu:在设置了过期时间的key中,删除最近最少频次使用的key。
  • allkeys-lfu:在全部的key中,删除最近最少频次使用的key。
  • volatile-random:在设置了过期时间的key中,随机删除key。
  • allkeys-random:在全部的key中,随机删除key。
  • volatile-ttl:删除剩余生存时间最少的key。
  • noeviction:不删除key,直接报错。

缓存的各种问题

Redis的事务,持久化,主从,哨兵,集群以及常见问题_第1张图片

你可能感兴趣的:(Linux,Docker,Redis)