大家好,又见面了,我是你们的朋友全栈君。
文章目录
- Redis持久化
- RDB(Redis DataBase)
- AOF(Append Only File)
- Redis发布订阅
- Redis 主从复制
- 哨兵模式
Redis持久化
Redis是内存数据库,如果不见内存中的数据库状态保存到磁盘,那么一旦服务器进程退出,服务器中的数据库状态也会消失。所以Redis提供了持久化功能
RDB(Redis DataBase)
什么是RDB: 在指定的时间间隔内将内存中的数据集快照写入内存, 也就是行话讲的Snapshot快照,他恢复时是将快照文件直接读到内存中。 Redis会单独创建一个子进程来持节话,会先将数据写入到一个临时文件中,待持久化过程都结束了。再用这个临时文件替换上次持久化好的文件。整个过程中,主进程都不参与IO操作,这就极高的提升了性能。如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方实要比AOF方实更加高效。RDB缺点是最后一次持久化后的数据可能丢失。 等下一次启动Redis的时候,会将持久化文件恢复到内存 rdb配置
代码语言:javascript复制save 60 5 //60s内修改5个值就会自动执行持久化
dbfilename dump.rdb //文件
# 都是再配置文件中进行的配置
持久化触发 1)手动触发 手动触发持久化的操作有两个:save 和 bgsave ,它们主要区别体现在:是否阻塞 Redis 主线程的执行。
- save 命令 在客户端中执行 save 命令,就会触发 Redis 的持久化,但同时也是使 Redis 处于阻塞状态,直到 RDB 持久化完成,才会响应其他客户端发来的命令,
- bgsave 命令 bgsave(background save)既后台保存的意思, 它和 save 命令最大的区别就是 bgsave 会 fork() 一个子进程来执行持久化,整个过程中只有在 fork() 子进程时有短暂的阻塞,当子进程被创建之后,Redis 的主进程就可以响应其他客户端的请求了。
2)自动触发 说完了 RDB 的手动触发方式,下面来看如何自动触发 RDB 持久化?RDB 自动持久化主要来源于以下几种情况
- save的规则满足的情况下,会自动生成rdb文件
- 执行flushall命令,也会生成rdb文件
- 退出redis,也会产生rdb文件
- 主从同步触发:在 Redis 主从复制中,当从节点执行全量复制操作时,主节点会执行 bgsave 命令,并将 RDB 文件发送给从节点,该过程会自动触发 Redis 持久化。
系统如果获得rdb文件? 只要将rdb文件放在我们redis启动目录就可以,redis启动的时候会自动检查dump.rdb恢复其中的数据 查看redis启动目录
代码语言:javascript复制127.0.0.1:6379> config get dir
1) "dir"
2) "/var/lib/redis" //rdb文件应该存在这个目录下面
优点:
- 适合大规模数据恢复
- 对数据的完整性要求不高 缺点
- 需要一定的事件间隔操作,如果redis意外宕机了,这个最后一次修改数据就没有了
- fork进程的时候,会占用一定的内存空间
AOF(Append Only File)
将我们的所有命令都记下来,恢复的时候把我们的命令全部都重新执行一边。 以日志的形式来记录每个写操作,将Redis执行过的所有指令记录下来(读操作不记录),之追加文件但不可以改写文件,Redis启动之初会读取该文件重新构建数据,换言之,redis重启的话就根据日志文件的内容写执行从前到后执行一次以恢复内存。 OF 重写函数会进行大量的写入操作,调用该函数的线程将被长时间阻塞,所以 Redis 在子进程中执行 AOF 重写操作。
- 子进程进行 AOF 重写期间,Redis 进程可以继续处理客户端命令请求。
- 子进程带有父进程的内存数据拷贝副本,在不适用锁的情况下,也可以保证数据的安全性。 但是,在子进程进行 AOF 重启期间,Redis接收客户端命令,会对现有数据库状态进行修改,从而导致数据当前状态和 重写后的 AOF 文件所保存的数据库状态不一致。
为此,Redis 设置了一个 AOF 重写缓冲区,这个缓冲区在服务器创建子进程之后开始使用,当 Redis 执行完一个写命令之后,它会同时将这个写命令发送给 AOF 缓冲区和 AOF 重写缓冲区。
当子进程完成 AOF 重写工作之后,它会向父进程发送一个信号,父进程在接收到该信号之后,会调用一个信号处理函数,并执行以下工作:
- 将 AOF 重写缓冲区中的所有内容写入到新的 AOF 文件中,保证新 AOF 文件保存的数据库状态和服务器当前状态一致。
- 对新的 AOF 文件进行改名,原子地覆盖现有 AOF 文件,完成新旧文件的替换
- 继续处理客户端请求命令。
AOF保存到appendonly,aof文件
代码语言:javascript复制# redis.conf
appendonly yes //手动开启aof
appendfilename 'appendonly aof' //生成的文件名
appendsync everysec //每秒都会追加一次
appendsync always //每次修改都记录
appendsync no //不执行 sync 这个时候操作系统同步数据
auto-aof-rewrite-percenttage = 100 //配置较前一个aof文件大小增长的百分比
auto-aof-rewrite-min-size 64mb //配置触发aof重写的aof的最小的大小。
....配置
ubuntu查找aop文件所在目录
代码语言:javascript复制127.0.0.1:6379> config get dir
1) "dir"
2) "/var/lib/redis" //aop文件在这个目录下
代码语言:javascript复制127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> set k2 v2
OK
127.0.0.1:6379> set k3 v3
OK
appendonly.aof文件如下
现在我们破坏先删除rdb文件,再破坏aop文件。 下图为随机破坏aop文件
然后启动redis发现不能正常启动
这个时候我们需要redis-check-aof文件修复 appendonly.aop文件
代码语言:javascript复制redis-check-aof --fix appendonly,aof //修复aof文件,再次启动就是正常启动
优点
- 可以设置每一次修改都同步,文件的完整性更好
- 可以设置每秒同步一次,可能会丢失一秒的数据
- 也可以设置从不同步,这样效率最高 缺点
- 相对于数据文件来说,aof远远大于rdb,修复速度也比rdb慢
- Aof运行效率比rdb慢,一般情况下都选择rdb
注意 Redis服务器重启时会优先加载aof文件来恢复数据
Redis发布订阅
Redis发布订阅pub/sub是一种消息通信模式:发布者(pub)发送消息,订阅者(sub)接收消息。 应用场景微信,微博,关注系统! 订阅/发布消息:
相关命令
ubuntu测试
代码语言:javascript复制# 客户端1订阅一个
127.0.0.1:6379> PSUBSCRIBE ccmessageccmessage频道
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "ccmessage"
3) (integer) 1
# 客户端2发送一个消息
127.0.0.1:6379> PUBLISH ccmessage 'hello cc'
(integer) 1
# 客户端1接受到消息
1) "pmessage"
2) "ccmessage"
3) "ccmessage"
4) "hello cc"
Redis是用c实现的,通过publish,subsscribe和psubscribe等命令发布和订阅功能 通过subscribe命令订阅某频道后,redis-server里面维护了一个字典,字典的键就是一个个频道,而字典的值就是一个链表,链表中保存在所有订阅这个channel的客户端,subscribe命令的关键就是将客户端添加到给定channel的订阅系统中。 通过Publish命令向订阅者发送信息,redis-server会使用给定的频道作为键,在它所维护的频道字典中朝朝记录了订阅这个频道的所有客户端的链表,将消息发布给所有订阅者。
Redis 主从复制
主从复制,读写分离! 80% 的情况下都是在进行读操作!减缓服务器的压力!架构中经常使用! 一主二从!只要在公司中,主从复制就是必须要使用的,因为在真实的项目中不可能单机使用Redis!
概念 主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(Master/Leader),后者称为从节点(Slave/Follower), 数据的复制是单向的!只能由主节点复制到从节点(主节点以写为主、从节点以读为主)。
默认情况下,每台Redis服务器都是主节点,一个主节点可以有0个或者多个从节点,但每个从节点只能由一个主节点。 作用
- 数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余的方式。
- 故障恢复:当主节点故障时,从节点可以暂时替代主节点提供服务,是一种服务冗余的方式
- 负载均衡:在主从复制的基础上,配合读写分离,由主节点进行写操作,从节点进行读操作,分担服务器的负载;尤其是在多读少写的场景下,通过多个从节点分担负载,提高并发量。
- 高可用基石:主从复制还是哨兵和集群能够实施的基础。
# 查看当前库的信息
127.0.0.1:6379> info replication
# Replication
role:master # 主机
connected_slaves:0 //从机数量
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
搭建集群环境 赋值3个配置文件redis.conf,然后修改相应信息
- 端口
- pid名字
- logfile
- dbfilename
启动三个Redis服务器
代码语言:javascript复制root@ubuntu:/etc/redis# redis-server redis.conf
root@ubuntu:/etc/redis# redis-server redis-1.conf
root@ubuntu:/etc/redis# redis-server redis-2.conf
root@ubuntu:/etc/redis# ps -ef | grep redis
root 2853 1568 0 18:59 ? 00:00:00 redis-server 127.0.0.1:6379
root 2859 1568 0 18:59 ? 00:00:00 redis-server 127.0.0.1:6380
root 2863 1568 0 18:59 ? 00:00:00 redis-server 127.0.0.1:6381
配置从机,使得6379为主机,6380,6381的为从机
代码语言:javascript复制127.0.0.1:6380> SLAVEOF 127.0.0.1 6379
OK
# 查看从机信息
127.0.0.1:6380> info replication
# Replication
role:slave // 这是一个从机
master_host:127.0.0.1 //主机地址
master_port:6379 //主机端口号
master_link_status:up
master_last_io_seconds_ago:3
master_sync_in_progress:0
slave_repl_offset:29
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
同理配置6381端口
查看主机6379的信息
代码语言:javascript复制root@ubuntu:/etc/redis# redis-cli -p 6379
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2 //有两个从机
slave0:ip=127.0.0.1,port=6380,state=online,offset=281,lag=0
slave1:ip=127.0.0.1,port=6381,state=online,offset=281,lag=1
master_repl_offset:281
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:280
注意 我们一般情况下是通过配置文件配置主从机。
主机可以写,从机只能读,主机中的所有信息都会被从机保存
代码语言:javascript复制# 从机不能写
127.0.0.1:6380> set name cc
(error) READONLY You can't write against a read only slave.
代码语言:javascript复制# 主机写后 从机可以读
root@ubuntu:/etc/redis# redis-cli -p 6379
127.0.0.1:6379> set name cc //主机写
OK
127.0.0.1:6379> exit
root@ubuntu:/etc/redis# redis-cli -p 6380 //从机读
127.0.0.1:6380> get name
"cc"
经过测试后,得出以下结论 主机断开连接,从机依旧连接到主机的,但是没有写操作,这个时候,主机如果回来了,丛集依旧可以直接获取到主机写的信息。 如果是使用命令行配置的主从机,这个时候如果重启了。就会变回主机,只要变为从机,立马就会从主机中获取值。
复制原理
Slave启动成功连接到master后会发送一个sync同步命令,Master接收到命令,启动后台的进程,同时收集所有接收到的用于修改数据集命令,在后台进程执行完毕之后,master将传送整个数据文件到slave,并完成一次完全同步。
- 全是复制:而slave服务在接受到数据库文件数据后,将齐存盘并加载到内存中
- 增量复制:Master继续将新的所有收集到的修改命令以此传给slave,完成同步
但是只要是重新连接master,一次完全同步将被自动执行,我们的数据一定可以在从机看到。
哨兵模式
手动配置
上图种80即是79的从机,也是81的主机
代码语言:javascript复制127.0.0.1:6381> SLAVEOF 127.0.0.1 6380 //连接6380到6381上
OK
# 6380此时即是6379 的从机,也是6381的主机
127.0.0.1:6380> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:9
master_sync_in_progress:0
slave_repl_offset:12557
slave_priority:100
slave_read_only:1
connected_slaves:1
slave0:ip=127.0.0.1,port=6381,state=online,offset=57,lag=1
master_repl_offset:57
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:56
# 给6379主机设置name字段,在6380 和 6381种皆可获得,这就是主从配置的传递性
127.0.0.1:6379> set name cc
OK
127.0.0.1:6379> exit
root@ubuntu:/etc/redis# redis-cli -p 6380 //6380中可以获得值
127.0.0.1:6380> get name
"cc"
127.0.0.1:6380>
root@ubuntu:/etc/redis# redis-cli -p 6381 //6381中也可获得值
127.0.0.1:6381> get name
"cc"
127.0.0.1:6380> set age 13
(error) READONLY You can't write against a read only slave. //6380即是主机,也是从机,只要是从机就不能写
127.0.0.1:6379> shutdown //此时手动关闭6379 则从机自动断开与6379的联系
not connected> exit
root@ubuntu:/etc/redis# redis-server redis.conf //此时再次开启6379 也不会恢复主从关系
127.0.0.1:6379> info replication //此时6379中没有任何从机,需要再次手动配置主从关系
# Replication
role:master
connected_slaves:1
slave0:ip=127.0.0.1,port=6380,state=online,offset=113,lag=0
master_repl_offset:113
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:112
可以使用SLAVEOF no one让自己变成主机。其他的节点就可以手动连接到最新的这个主节点
自动配置(哨兵模式) 主从切换技术的方法是:当主服务器宕机后,需要手动把一台从服务器切换为主服务器,这就需要人工干预,费事费力,还会造成一段时间内服务不可用。这不是一种推荐的方式,更多时候,我们优先考虑哨兵模式。Redis从2.8开始正式提供了Sentinel(哨兵) 架构来解决这个问题。能够后台监控主机是否故障,如果故障了根据投票数自动将从库转换为主库。
哨兵模式是一种特殊的模式,首先Redis提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行。其原理是哨兵通过发送命令,等待Redis服务器响应,从而监控运行的多个Redis实例。
哨兵的作用:
- 通过发送命令,让Redis服务器返回监控其运行状态,包括主服务器和从服务器。
- 当哨兵监测到master宕机,会自动将slave切换成master,然后通过发布订阅模式通知其他的从服务器,修改配置文件,让它们切换主机。 然而一个哨兵进程对Redis服务器进行监控,可能会出现问题,为此,我们可以使用多个哨兵进行监控。各个哨兵之间还会进行监控,这样就形成了多哨兵模式。
假设主服务器宕机,哨兵1先检测到这个结果,系统并不会马上进行failover过程,仅仅是哨兵1主观的认为主服务器不可用,这个现象成为主观下线。当后面的哨兵也检测到主服务器不可用,并且数量达到一定值时,那么哨兵之间就会进行一次投票,投票的结果由一个哨兵发起,进行failover[故障转移]操作。切换成功后,就会通过发布订阅模式,让各个哨兵把自己监控的从服务器实现切换主机,这个过程称为客观下线。
配置哨兵
- 配置哨兵文件sentinel.conf文件
# sentinel monitor 被监控的名称 host port 1
sentinel monitor myredis 127.0.0.1 6379 1 # 后面的这个数字1,代表主机挂了,slave投票看让谁接替成为主机,票数最多的,就会成为主机!
- 启动哨兵!
3. 此时哨兵监视着我们的主机6379,当我们断开主机后:
注意 当原主机回来的时候,会变为一个从机。
哨兵模式优缺点 优点:
- 哨兵集群,基于主从复制模式,所有主从复制的优点,它都有
- 主从可以切换,故障可以转移,系统的可用性更好
- 哨兵模式是主从模式的升级,手动到自动,更加健壮 缺点: 缺点
- Redis不好在线扩容,集群容量一旦达到上限,在线扩容就十分麻烦
- 实现哨兵模式的配置其实是很麻烦的,里面有很多配置项
# Example sentinel.conf
哨兵sentinel实例运行的端口 默认26379
port 26379
哨兵sentinel的工作目录
dir /tmp
哨兵sentinel监控的redis主节点的 ip port
master-name 可以自己命名的主节点名字 只能由字母A-z、数字0-9 、这三个字符".-_"组成。
quorum 当这些quorum个数sentinel哨兵认为master主节点失联 那么这时 客观上认为主节点失联了
sentinel monitor <master-name> <ip> <redis-port> <quorum>
sentinel monitor mymaster 127.0.0.1 6379 1
当在Redis实例中开启了requirepass foobared 授权密码 这样所有连接Redis实例的客户端都要提供密码
设置哨兵sentinel 连接主从的密码 注意必须为主从设置一样的验证密码
sentinel auth-pass <master-name> <password>
sentinel auth-pass mymaster MySUPER--secret-0123passw0rd
指定多少毫秒之后 主节点没有应答哨兵sentinel 此时 哨兵主观上认为主节点下线 默认30秒
sentinel down-after-milliseconds <master-name> <milliseconds>
sentinel down-after-milliseconds mymaster 30000
这个配置项指定了在发生failover主备切换时最多可以有多少个slave同时对新的master进行 同步,
这个数字越小,完成failover所需的时间就越长,
但是如果这个数字越大,就意味着越 多的slave因为replication而不可用。
可以通过将这个值设为 1 来保证每次只有一个slave 处于不能处理命令请求的状态。
sentinel parallel-syncs <master-name> <numslaves>
sentinel parallel-syncs mymaster 1
故障转移的超时时间 failover-timeout 可以用在以下这些方面:
1. 同一个sentinel对同一个master两次failover之间的间隔时间。
2. 当一个slave从一个错误的master那里同步数据开始计算时间。直到slave被纠正为向正确的master那里同步数据时。
3.当想要取消一个正在进行的failover所需要的时间。
4.当进行failover时,配置所有slaves指向新的master所需的最大时间。不过,即使过了这个超时,slaves依然会被正确配置为指向master,但是就不按parallel-syncs所配置的规则来了
默认三分钟
sentinel failover-timeout <master-name> <milliseconds>
sentinel failover-timeout mymaster 180000
SCRIPTS EXECUTION
配置当某一事件发生时所需要执行的脚本,可以通过脚本来通知管理员,例如当系统运行不正常时发邮件通知相关人员。
对于脚本的运行结果有以下规则:
若脚本执行后返回1,那么该脚本稍后将会被再次执行,重复次数目前默认为10
若脚本执行后返回2,或者比2更高的一个返回值,脚本将不会重复执行。
如果脚本在执行过程中由于收到系统中断信号被终止了,则同返回值为1时的行为相同。
一个脚本的最大执行时间为60s,如果超过这个时间,脚本将会被一个SIGKILL信号终止,之后重新执行。
通知型脚本:当sentinel有任何警告级别的事件发生时(比如说redis实例的主观失效和客观失效等等),将会去调用这个脚本,
这时这个脚本应该通过邮件,SMS等方式去通知系统管理员关于系统不正常运行的信息。调用该脚本时,将传给脚本两个参数,
一个是事件的类型,
一个是事件的描述。
如果sentinel.conf配置文件中配置了这个脚本路径,那么必须保证这个脚本存在于这个路径,并且是可执行的,否则sentinel无法正常启动成功。
通知脚本
sentinel notification-script <master-name> <script-path>
sentinel notification-script mymaster /var/redis/notify.sh
客户端重新配置主节点参数脚本
当一个master由于failover而发生改变时,这个脚本将会被调用,通知相关的客户端关于master地址已经发生改变的信息。
以下参数将会在调用脚本时传给脚本:
<master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>
目前<state>总是“failover”,
<role>是“leader”或者“observer”中的一个。
参数 from-ip, from-port, to-ip, to-port是用来和旧的master和新的master(即旧的slave)通信的
这个脚本应该是通用的,能被多次调用,不是针对性的。
sentinel client-reconfig-script <master-name> <script-path>
sentinel client-reconfig-script mymaster /var/redis/reconfig.sh
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/168800.html原文链接:https://javaforall.cn