zoukankan      html  css  js  c++  java
  • 三千字介绍Redis主从+哨兵+集群

    一、Redis持久化策略

    1.RDB

    每隔几分钟或者一段时间会将redis内存中的数据全量的写入到一个文件中去。

    优点:

    1. 因为他是每隔一段时间的全量备份,代表了每个时间段的数据。所以适合做冷备份。
    2. RDB对redis的读写影响非常小,因为redis主进程只需要fork一个子进程进行磁盘IO操作就行了。
    3. 相对于AOF来说,恢复较快,因为一个RDB就是数据文件,而AOF存的是指令日志。

    缺点:

    1. 因为是一段时间才备份,所以容易丢数据。
    2. 如果一次写入的文件大,会导致读写服务暂停几毫秒,甚至几秒。

    2.AOF

    会将每条写入指令都写入到linux os缓存中去,然后每秒钟会将linux os中的指令作为日志追加到AOF的文件里面。

    当redis内存大小达到一定的量,会通过LRU(最近最少使用)淘汰机制淘汰掉数据,然后再重写一个新的AOF文件出来。这样也保证了AOF文件不会无限制的增大。

    优点:

    1. 不易丢数据
    2. AOF日志文件是以append-only的模式写入,没有磁盘寻址的开销,写入性能高,文件也不易破损
    3. AOF文件过大的时候,后台重写操作,也不会影响客户端。再rewrite的时候,会对指令压缩,创建出一份需要恢复的最小日志出来,再创建新日志文件时,老的文件照常写入,当新文件准备好了,再交换新老日志文件就行了
    4. 日志文件的命令是可读的,可以作为误删的紧急恢复。停了服务,再把那条删除指令删除,再恢复就行了。

    缺点:

    1. AOF日志文件占用的磁盘空间比较大
    2. 开启AOF后,写操作的QPS会下降
    3. 以前出过bug,恢复的数据和原来不一样,健壮性没有RDB高
    4. 恢复数据慢,且不适合做冷备(需要手动写脚本)

    3.混合持久化(Redis 4.0)

    开启混合持久化

    aof-use-rdb-preamble yes

    综合来说:

    我们可以采用两种都用的的方案,RDB做冷备,为了保证数据不丢失,AOF做数据恢复的第一选择。

    如何配置持久化?

    1. 找到/usr/local/package/redis-4.0.9/redis.conf

    2. RDB的配置

     //每隔60秒,如果有10000个key发生改变就持久化一次
        save 60 10000
    
    1. AOF的配置
        # redis默认关闭AOF机制,可以将no改成yes实现AOF持久化
        appendonly no
        # AOF文件
        appendfilename "appendonly.aof"
        # AOF持久化同步频率,always表示每个Redis写命令都要同步fsync写入到磁盘中,但是这种方式会严重降低redis的速度;everysec表示每秒执行一次同步fsync,显示的将多个写命令同步到磁盘中;no表示让操作系统来决定应该何时进行同步fsync,Linux系统往往可能30秒才会执行一次
        # appendfsync always
        appendfsync everysec
        # appendfsync no
        
        # 在日志进行BGREWRITEAOF时,如果设置为yes表示新写操作不进行同步fsync,只是暂存在缓冲区里,避免造成磁盘IO操作冲突,等重写完成后在写入。redis中默认为no  
        no-appendfsync-on-rewrite no   
        # 当前AOF文件大小是上次日志重写时的AOF文件大小两倍时,发生BGREWRITEAOF操作。  
        auto-aof-rewrite-percentage 100  
        #当前AOF文件执行BGREWRITEAOF命令的最小值,避免刚开始启动Reids时由于文件尺寸较小导致频繁的BGREWRITEAOF。  
        auto-aof-rewrite-min-size 64mb  
        # Redis再恢复时,忽略最后一条可能存在问题的指令(因为最后一条指令可能存在问题,比如写一半时突然断电了)
        aof-load-truncated yes
        #Redis4.0新增RDB-AOF混合持久化格式,在开启了这个功能之后,AOF重写产生的文件将同时包含RDB格式的内容和AOF格式的内容,其中RDB格式的内容用于记录已有的数据,而AOF格式的内存则用于记录最近发生了变化的数据,这样Redis就可以同时兼有RDB持久化和AOF持久化的优点(既能够快速地生成重写文件,也能够在出现问题时,快速地载入数据)。
        aof-use-rdb-preamble no
    
    1. AOF rewrite过程

      1. redis fork一个子进程
      2. 子进程基于当前内存中的数据开始写入一个新的aof的文件
      3. 这时新的命令进来,会存在内存中,也会存在旧的aof文件中
      4. 当新的aof文件写好了,这个过程中的新的命令也会追加到aof里来
      5. 然后用新日志文件替换掉旧的日志文件

    注意:当使用shutdown命令关闭redis服务时,会自动备份一个快照

    当RDB生成快照时,AOF不会rewrite。反之亦然。

    redis如果遇到断电或机器故障问题时怎么办?

    答:一般使用持久化加服务器文件(将文件备份到阿里云)备份的方案

    二、Redis淘汰策略

    LRU:(least recently used)最近最少使用

    1. 标准的LRU算法:

    使用HashMap+双向链表

    核心步骤:

    1. save操作时,在hashmap中找对应的key值,如果存在,更新他并移到队头,如果不存在,则构建新节点,并移到队头,如果队列满了,则移除队尾的节点,并在hashmap中移除该key
    2. get操作时,在hashmap中找到对应的节点,将他移到队头

    redis里面没有使用双向链表的实现方式,而是使用了一个pool池.

    1. Redis的LRU实现

    常用策略:allkeys-lru

    Redis使用的是近似LRU算法

    • 给每个 key 增加一个额外 24bit 长度的小字段, 存储该 key 的最后一次访问时间戳
    • 当空间满时, 随机采样取出 5 个 key (数量可配置), 按时间戳淘汰掉最旧的 key
    • 循环第二步, 直到内存低于 maxmemory 值
    • 随机采样的范围取决于配置的策略是 volatile 还是 allkeys

    Redis 3.0 开始, 增加了淘汰池进一步提升了近似 LRU 的效果:

    • 上一次随机采样后未淘汰的 key, 会放入 淘汰池 留待下一次循环,
    • 下一次随机采样的key会先和淘汰池中的key合并后, 再计算淘汰最旧的key

    三、Redis主从架构

    1.主从特性

    1. 采用异步的方式复制到slave节点,不过redis2.8之后,每个slave节点会周期性的确认自己每次复制的数据量
    2. 一个master可以配置多个slave
    3. slave node也可以连接其他的slave node
    4. slave复制时不影响master的工作
    5. slave复制时也不会影响slave的查询操作,他会用旧的数据提供服务。但是当复制完成,需要删除旧数据,加载新数据集时,会暂停服务。
    6. slave主要用来做横向扩容,做读写分离

    2.主从复制步骤

    1. 当slave第一次连接时,master会生成一个全量RDB文件给他做恢复,并将这个过程中新的写入命令缓存在内存中,等slave把RDB文件读入之后发给他
    2. 当slave断开一段时间后重连,master会将缺失的数据发给他
    3. 平时情况下,master收到一个指令,都会马上复制给slave

    3.断点续传
    从redis2.8开始,就支持主从复制的断点续传
    master中存了backlog,master和slave都会保存一个replica offset,还有一个master id。如果中途网络断了,slave会让master从上次的replica offset开始继续复制。

    4.过期key处理
    slave不会过期key,只会等master过期key之后或者根据,模LRU淘汰了key之后拟一个del命令发给slave

    5.配置主从服务器

    1. 安装redis
    2. cp utils/redis_init_script /etc/init.d/redis_6379
    3. redis自启动 chkconfig redis_6379 on
    4. mkdir /etc/redis
    5. mkdir -p /var/redis/6379
    6. cp redis.conf /etc/redis/6379.conf
    7. 修改配置文件6379.conf
    • daemonize yes //让redis以daemon进程运行
    • dir /var/redis/6379
    • slaveof CentOS01 6379
    • slave 服务器的配置文件上配 masterauth 123456
    • master服务器的配置文件上配
      requirepass 123456
    • 每个6379.conf里都要将bind 127.0.0.1改成bind 自己本机的ip
    1. 让redis跟随系统启动自动启动

    在redis_6379脚本中,最上面,加入两行注释

    #chkconfig:   2345 90 10  
    #description:  Redis is a persistent key-value database
    

    然后执行
    chkconfig redis_6379 on
    8. 压测性能 ./redis-benchmark -c 50 -n 10000

    复制原理图:

    注意:主从架构建议必须开启master节点的持久化。

    四、哨兵模式

    1.概念介绍

    介绍:

    1. 集群监控,监控master和slave是否正常
    2. 消息通知,如果某个redis实例故障了,负责发消息给管理员
    3. 故障转移,如果master节点挂掉了,会自动转移到slave上
    4. 配置中心,如果故障转移发生了,通知client新的master地址

    2.故障转移

    哨兵至少要3个实例

    如图:

    如果只有2个哨兵会如何呢?

    master宕机,s1和s2中只要有1个哨兵认为master宕机就可以进行切换,同时s1和s2中会选举出一个哨兵来执行故障转移

    同时这个时候,需要majority,也就是大多数哨兵都是运行的,2个哨兵的majority就是2(2的majority=2,3的majority=2,5的majority=3,4的majority=2),2个哨兵都运行着,就可以允许执行故障转移

    但是如果整个M1和S1运行的机器宕机了,那么哨兵只有1个了,此时就没有majority来允许执行故障转移,虽然另外一台机器还有一个R1,但是故障转移不会执行

    3.解决异步复制和脑裂导致的数据丢失

    min-slaves-to-write 1
    min-slaves-max-lag 10
    要求至少有1个slave,数据复制和同步的延迟不能超过10秒

    4.sdown和odown转换机制
    sdown:主观宕机,即一个哨兵觉得master宕机了
    odown:客观宕机,即quorum数量的哨兵觉得master宕机了

    5.哨兵集群的自动发现机制

    哨兵互相之间的发现,是通过redis的pub/sub系统实现的,每个哨兵都会往__sentinel__:hello这个channel里发送一个消息,这时候所有其他哨兵都可以消费到这个消息,并感知到其他的哨兵的存在

    每隔两秒钟,每个哨兵都会往自己监控的某个master+slaves对应的__sentinel__:hello channel里发送一个消息,内容是自己的host、ip和runid还有对这个master的监控配置

    每个哨兵也会去监听自己监控的每个master+slaves对应的__sentinel__:hello channel,然后去感知到同样在监听这个master+slaves的其他哨兵的存在

    每个哨兵还会跟其他哨兵交换对master的监控配置,互相进行监控配置的同步

    6.选举算法

    如果一个master被认为odown了,而且majority哨兵都允许了主备切换,那么某个哨兵就会执行主备切换操作,此时首先要选举一个slave来

    会考虑slave的一些信息

    (1)跟master断开连接的时长
    (2)slave优先级
    (3)复制offset
    (4)run id

    7.部署哨兵

    1. 复制配置文件
        mkdir -p /var/sentinel/5000
        mkdir /etc/sentinel
        mkdir -p /var/log/sentinal/5000
        mv /usr/local/package/redis-4.0.9/sentinel.conf /etc/sentinel/5000.conf
    
    1. 修改配置文件
      port 5000
      bind  192.168.1.14
      sentinel monitor mymaster 192.168.1.12 6379 2
      dir /var/sentinel/5000
      sentinel parallel-syncs mymaster 1
      sentinel failover-timeout mymaster 60000
      sentinel down-after-milliseconds mymaster 30000
      sentinel auth-pass mymaster 123456
      daemonize yes
      logfile /var/log/sentinal/5000/sentinel.log
    

    注意:sentinel monitor mymaster 192.168.1.12 6379 2 这行要放在使用mymaster的那些其他配置之前

    1. 启动哨兵

    ./redis-sentinel /etc/sentinel/5000.conf

    五、redis集群

    1.概念介绍

    1. 自动对数据进行分片,每个master上存放一部分数据
    2. 提供内置的高可用支持,部分master不可用了,还是可以继续工作的

    2.部署选型
    redis cluster VS replication + sentinel

    当数据量少,主要承载的是高并发时,单机就足够了。一个master多个slave,在搭建一个sentinel集群来保证高可用性

    redis cluster主要还是用来做海量数据的缓存。

    3.分布式Hash算法

    当需要把数据分到不同的几个机器存储时,就需要一个算法了。

    1. 方法一:取模
      对数据的hash值取模,比如有3台集器,那么就用hash%3,得到的就是0-2的三个数字,就可以确定将数据存在哪一台上面了

    缺点:如果有一台机器挂掉了,那么数据会对2取模,那么得到的机器号就错乱了,导致大量数据不能从正确的机器上去取

    1. 方法二:一致性hash算法(圆环算法)

    将3台机器放在一个圆环上,然后要缓存的数据经过计算也落在圆环的某一个点,然后顺时针去环上找离他最近的那个机器。

    优点:当一台机器挂掉,不影响其他的机器上存的数据

    缺点:具有热点问题,可能某一个机器会有大量数据,这就需要将每个机器都多设置几个虚拟节点,均匀分布在圆环上。

    1. 方法三:redis cluster的hash slot算法

    redis cluster有固定的16384个slot,对每个key计算CRC16值,然后对16384取模,获取对应的slot,每个master都有部分的slot。这样的话如果增加一个master,就将其他master上的slot分点给她就行了。

    4.部署redis集群

    1. 创建目录
      mkdir -p /etc/redis-cluster
      mkdir -p /var/log/redis
      mkdir /var/redis/7001
      mkdir /var/redis/7002
    
    1. 修改配置文件 7001.conf
      port 7001
      cluster-enabled yes
      cluster-config-file /etc/redis-cluster/node-7001.conf
      cluster-node-timeout 15000
      pidfile "/var/run/redis_7001.pid"
      dir "/var/redis/7001"
      logfile "/var/log/redis/7001.log"
    
    1. 修改配置文件
    vi /usr/local/share/gems/gems/redis-3.2.1/lib/redis/client.rb
    
    password=123456
    
    1. 执行
     echo never > /sys/kernel/mm/transparent_hugepage/enabled
    
    1. 启动脚本
       cd /etc/init.d/
       cp redis_6379 redis_7001
    修改redis_7001配置
    
      REDISPORT=7001
    
    1. 安装ruby
       yum install -y ruby
        下载一个redis-3.2.1.gem,然后执行
        gem install redis
        
        cp /usr/local/package/redis-4.0.9/src/redis-trib.rb /usr/local/bin
        
        /usr/local/bin/redis-trib.rb create --replicas 1 192.168.1.12:7001 192.168.1.12:7002 192.168.1.13:7003 192.168.1.13:7004 192.168.1.14:7005 192.168.1.14:7006
    
    1. 检查节点状态
     ./redis-trib.rb check 192.168.1.12 7001
    
    书山有路勤为径,学海无涯苦作舟
  • 相关阅读:
    分布式消息系统Kafka初步
    webService 学习
    一个周末掌握IT前沿技术之node.js篇
    mount
    dd
    fsck
    resize2fs
    mkfs
    parted
    tune2fs
  • 原文地址:https://www.cnblogs.com/javammc/p/15358177.html
Copyright © 2011-2022 走看看