redis扩展

哈希一致性算法

集群中,数据如何均匀的存储在多台服务器中
1、hash(key) %len(服务器)   
  问题:机器数量变动,会有大量的数据移动
  2^32 65535  槽位用来挂载机器;当机器变动时,只会移动与当前机器绑定的操作与相邻槽位机器之间的数据移动;
          -->哈希环上散列的值越多(经验 环1000+才会均衡),变动越小

此算法问题:
  机器少时;会有少量机器存储大量数据的情况产生
  ->  虚拟节点 每个机器虚拟多个节点,一定程度可以解决;

 

 

 

持久化

RDB:根据指定的规则‘定时’将内存中的数据存储到硬盘上

AOF:每次在执行命令后将命令本身记录下来

一般都是二者一起用

RDB方式 
rdb方式的持久化是通过快照完成的,当符合一定条件时redis会自动将内存中的所有数据生成一份副本并存储到硬盘上,这个过程即为‘快照’,
  什么情况进行快照
  • 根据用户规则进行自动快照
    • redis.conf默认有3行
      save 900 1
      save 300 10
      save 60 10000

      以第一条为例:表示在900秒内至少有1个键被修改则进行快照

  • 用户执行SAVE或BGSAVE命令
    • 除了让redis自动进行快照外,当进行服务重启、手动迁移以及备份时时我们也需要会手动执行快照
    • save
      同步的执行快照操作,  在执行过程中会阻塞所有来自客户端的请求;
      当请求比较多时,这一过程会导致redis较长时间不响应
      bgsave
      与save不同  是异步,
      执行bgsave后立即返回OK表示开始执行快照操作,如果想知道快照是否完成,
      可以通过lastsave命令获取最近一次成功执行快照的时间,返回结果是一个时间戳

       

       

       

  • 执行FLUSHALL命令
    • 会清空所有数据
    • 不论这个过程是否触发了自动快照条件,只要自动快照条件不为空,redis就会执行一次快照操作
    • 当没有自定义快照条件时,执行flushall则不会进行快照  
  • 执行复制时
    • 当设置了主从模式时,redis会在复制初始化时进行自动快照 

 

快照原理
redis会默认将快照文件存储到redis当前进程的工作目录中的dump.rdb文件中
  dir
  dbfilename
快照的过程是
  • redis使用fork函数复制一份当前进程(父进程)的副本(子进程)
  • 父进程继续使用并接受处理客户端发来的命令,而子进程开始将内存中的数据写入硬盘的临时文件
  • 当子进程写入完所有数据后会用该临时文件替换旧的rdb文件,至此一次快照操作完成

在执行fork的时候操作系统(类unix)会使用写时复制策略,即fork函数发生的一刻父子进程共享统一内存数据,当父进程更改其中某片数据时,

os会将该片数据复制一份以保证子进程的数据不受影响,所以新的rdb文件存储的是fork那一时刻的内存数据;

注意:如果更改数据操作过多,会使内存使用量显著超过实际数据大小的,因为内存中不仅保存了当前的数据库数据,而且还保存着fork时刻的内存数据

 

rdb方式持久化,一旦异常退出,就会丢失最后一次快照以后更改的所有数据,

如果数据非常重要则需要使用aof方式进行持久化 

 

AOF方式
AOF可以将redis执行的每一条命令,追加到硬盘文件中,之一过程显然会降低性能
但大部分情况下这个情况是可以接受的,另外使用较快的硬盘可以提高AOF性能
appendonly        yes            # 默认没有打开是no

appendfilename            appendonly.aof
# 同步硬盘数据
# appendfsync    always      # 每次执行
appendfsync    everysec      # 每秒
# appendfsync  no          # 不进行
redis  允许同时开启AOF,RDB,既保证了数据安全又使得进行备份等操作十分容易。
此时重启redis后redis会使用AOF文件来恢复数据,因为AOF方式丢失的数据更少

集群

复制
通过持久化功能,redis保证了即使在在服务器重启的情况下也不会丢失(或少量丢失)数据。但是由于数据是存储在一台服务器上的,如果这台服务器出现硬盘故障等问题,
也会导致数据丢失。为了避免单点故障,通常的做法是将数据库复制多个副本以部署在不同的服务器上,这样即使有一台服务器出现故障,其他服务器依然可以继续提供服务。
为此redis提供了复制(replication)功能,实现当一台数据库中的数据更新后,自动将更新的数据同步到其他数据库上;简单可以理解为 主从复制
一般来说:    主数据库可以进行读写操作,当操作导致数据变化时会自动将数据同步给从数据库。
从数据库一般只是制度的,并接受主数据同步过来的数据
一个主可以有多个从,但一个从只能有一个主,同时每个redis服务器可以同时充当主、从服务器
使用方法:
主1:redis-server
从1:redis-server    --port    6380    --slaveof    127.0.0.1    6379
或者启动的时候不指定--slaveof
redis>    SLAVEOF    127.0.0.1    6379    (改过该数据已经是其他主数据的从数据了,会停止和原来数据库的同步而和新的数据库同步)
redis>    SLAVEOF    NO    ONE    (停止接受其他数据库的同步并转换成主数据)
从2:redis-server    --port    6381    --slaveof    127.0.0.1    6379
当master挂掉后,也需要手动地    通过slaveof 进行主从的切换



slaveof  on one
slaveof ip port
slave-read-only yes

  


# REDIS-CLI -P 6381 info replocation  # 查看状态 此时主数据库中的任何数据变化都回自动地同步到从数据库中 测试发现,当主服务器添加了数据后,从数据库会同步数据 默认从数据库只有读权限可以通过设置配置文件中的 slave-read-only 为 no 可是从数据库可写,但是修改后的数据不会同步到其他数据,所以通常情况下不会这么干
同步的原理:
从启动后会向主数据库发送SYNC命令
主接收到SYNC命令后(RDB开始);并将快照保存期间接受到的命令缓存起来。
RDB结束后,redis将快照文件和所有缓存的命令发送给从数据库
从数据库接收到,会载入快照文件并执行收到的缓存的命令。从而保证数据的一致性
乐观赋值策略,容忍一定时间内主从数据库的内容是不同的,但最终两者的数据库会同步, 因为二者异步+

 

※ 上述:主数据重新保存快照并传送给从数据库,即使从数据库仅有几条命令没有接受,主数据库也必须要将数据库里的所有数据重新传送给从数据库
这使得主从数据库断线重连后的数据恢复过程效率很低下,在网络差的环境下这一问题尤为明显。
------------------------>无硬盘复制
我们知道复制是基于RDB方式的持久化来实现的,即主数据端在后台保存RDB快照,从数据库端则接受并载入快照文件,这样的实现优点是可以显著地简化逻辑,
复用已有的代码,但是缺点也很明显
1、主数据禁用RDB快照时(删除配置文件中的save),此时执行了复制初始化操作,redis依然会生成RDB快照,所以下次启动主数据会以该快照恢复数据。 因为是复制发生的时间不能确定,这使得回复的数据可能是任何时间点的。 2、因为它要在硬盘创建RDB文件,所以如果硬盘的性能较慢时之一过程会对性能产生影响。 举例: 用redis做缓存系统时,因为不需要持久化,所以服务器的硬盘读写速度可能会比较差,但是当该缓存系统使用一主多从的集群架构时, 每次和从数据同步,redis都会执行一次快照,同时对硬盘进行读写,导致性能降低 从2.8.18版本开始后,redis引入了无硬盘复制选项,开启该选项时,redis在与从数据库进行复制初始化时将不会将快照文件存储到硬盘上,而是直接通过网络发送给从数据库,
避免了硬盘的性能瓶颈 如何开启: repl
-diskless-sync yes
------------------------>增量复制
基于如下3点实现的。
1、从数据库会存储主数据库的运行ID.每个redis运行实例均会拥有一个唯一的运行ID,
每当实例重启后,就会自动生成一个新的运行ID
2、在复制同步阶段,主数据库每将一条命令传送给从数据库时,都回同时把该命令存放到一个积压队列中,
并记录下当前挤压队列中存放的命令的偏移量范围。 
3、同时,从数据库接收到主数据传来的命令时,会记录下该命令的偏移量
※    PSYNC

 

增量复制的原理:
1、首先主数据会判断从数据库传送来的运行ID是否和自己的运行ID相同。这一步骤的意义在于确保从数据之前确实是和自己同步的,
一面从数据库拿到错误的数据(比如说主数据在短线期间重启过,会造成数据的不一致)
2、然后判断从数据最后同步成功的命令偏移量是否挤压队列中,如果在则可以执行增量复制,并将积压队列中相应的命令发送给从数据库
如果此次重连不满足增量复制的条件,主数据会进行一次全部同步
哨兵
https://www.cnblogs.com/pyyu/p/9718679.html

 

出现的情景:
主数据库遭到异常中断服务后,开发者可以通过手动的方式选择一个从数据库来升格为主数据库,一时的系统性能够继续提供服务。
然而真个过程相对玛法且需要人工介入,难以实现自动化
哨兵的功能:
1、监控主数据库和从数据库是否正常运行
2、主数据库出现故障时自动将从数据库转换为主数据库。
哨兵是一个独立的进程,一个一主多从的redis系统中,可以使用多个哨兵进行监控人物以保证系统足够文件,
此时不仅哨兵会同时监控主数据库和从数据库,哨兵之间也会互相监控
# 获取信息
redis> INFO    replication    

配置哨兵:
vim sentinel.conf
sentinel monitor mymaster 127.0.0.1:6379    1

# 1 最低通过票数    一般N/2 + 1
# 只配置主数据库即可,哨兵会自动发现所有复制该数据库的从数据库
# 然后启动哨兵
redis-sentinel ./sentinel.conf

 

哨兵的部署:
哨兵以独立进程的方式对一个主从系统进行监控,监控的效果好坏取与否决于哨兵的视角是否有代表性。如果一个主从系统中配置的哨兵较少,哨兵对整个系统的判断的可靠性就会降低。

 

// Sentinel节点的端口
port 26379  
dir /var/redis/data/
logfile "26379.log"

// 当前Sentinel节点监控 192.168.119.10:6379 这个主节点
// 2代表判断主节点失败至少需要2个Sentinel节点节点同意
// mymaster是主节点的别名
sentinel monitor mymaster 192.168.119.10 6379 2

//每个Sentinel节点都要定期PING命令来判断Redis数据节点和其余Sentinel节点是否可达,如果超过30000毫秒30s且没有回复,则判定不可达
sentinel down-after-milliseconds mymaster 30000

//当Sentinel节点集合对主节点故障判定达成一致时,Sentinel领导者节点会做故障转移操作,选出新的主节点,
原来的从节点会向新的主节点发起复制操作,限制每次向新的主节点发起复制操作的从节点个数为1
sentinel parallel-syncs mymaster 1

//故障转移超时时间为180000毫秒
sentinel failover-timeout mymaster 180000

  

redis-sentinel /etc/redis-sentinel-26380.conf

  

 

redis-cluster

redis集群方案,提供了哨兵+主从功能

  

通过配置,开启redis-cluster

port 7000
daemonize yes
dir "/opt/redis/data"
logfile "7000.log"
dbfilename "dump-7000.rdb"
cluster-enabled yes   #开启集群模式
cluster-config-file nodes-7000.conf  #集群内部的配置文件
cluster-require-full-coverage no  #redis cluster需要16384个slot都正常的时候才能对外提供服务,换句话说,只要任何一个slot异常那么整个cluster不对外提供服务。 因此生产环境一般为no

redis支持多实例的功能,我们在单机演示集群搭建,需要6个实例,三个是主节点,三个是从节点,数量为6个节点才能保证高可用的集群。

[root@yugo /opt/redis/config 17:12:30]#ls
redis-7000.conf  redis-7002.conf  redis-7004.conf
redis-7001.conf  redis-7003.conf  redis-7005.conf

准备ruby环境

第一步,安装ruby(这些命令可以放入一个sh脚本文件里)
wget https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.1.tar.gz

#安装ruby
tar -xvf ruby-2.3.1.tar.gz
./configure --prefix=/opt/ruby/
make && make install

#准备一个ruby命令
#准备一个gem软件包管理命令
#拷贝ruby命令到path下/usr/local/ruby
cp /opt/ruby/bin/ruby /usr/local/
cp bin/gem /usr/local/bin

第二步,安装ruby gem 包管理工具
wget http://rubygems.org/downloads/redis-3.3.0.gem

gem install -l redis-3.3.0.gem    # 安装ruby操作redis 的模块

#查看gem有哪些包
gem list -- check redis gem
第三步,安装redis-trib.rb命令
# 用于创建redis-cluster
[root@yugo /opt/redis/src 18:38:13]#cp /opt/redis/src/redis-trib.rb /usr/local/bin/

  

# 分配槽位,分配主从关系
#每个主节点,有一个从节点 --replicas 1 redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 #集群自动分配主从关系 7000、7001、7002为 7003、7004、7005 主动关系

  

使用

redis-cli -c -p 7000
这样会重定向到对应的槽位

  

查看集群状态

redis-cli -p 7000 cluster info  

redis-cli -p 7000 cluster nodes  #等同于查看nodes-7000.conf文件节点信息

集群主节点状态
redis-cli -p 7000 cluster nodes | grep master
集群从节点状态
redis-cli -p 7000 cluster nodes | grep slave

[root@yugo /opt/redis/src 18:42:14]#redis-cli -p 7000 cluster info

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 不重启   从RDB切换到AOF
确保redis版本在2.2以上    # redis-server -v

确保开启RDB

启动redis服务端 redis-server redis.conf

备份这个rdb文件,保证数据安全  cp dbmp.rdb /opt/

执行命令,开启AOF持久化  CONFIG set appendonly yes   #开启AOF功能

                       CONFIG SET save ""  #关闭RDB功能            



此时RDB已经正确切换AOF,注意还得修改redis.conf添加AOF设置,不然重启后,通过config set的配置将丢失

    

 

posted @ 2018-11-29 20:03  慕沁  阅读(340)  评论(0)    收藏  举报