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的配置将丢失

浙公网安备 33010602011771号