目录
前言
Redis和MySQL事务区别
事务操作
MULTI
EXEC
DISCARD
WATCH
UNWATCH
主从复制
配置主从复制
建立复制关系
info replication
断开复制
安全性
只读
传输延迟
拓扑
一主一从结构
一主多从结构
树形拓扑结构
原理
主从节点建立复制流程图
数据同步psync
replicationid/replid(复制id)
offset(偏移量)
psync运行流程:
全量复制
流程图
部分复制
流程图
复制积压缓冲区
实时复制
总结
主从复制特点
主从复制的配置过程
主从复制的缺点
前言
什么是事务 ?
其实Redis的事务和MySQL的事务概念上是一样的,都是把一系列的操作绑成一组,让这一组能够批量执行
Redis和MySQL事务区别
- 弱原子性:redis没有回滚机制,只能做到批量执行,并不能像MySQL一样一个错误全部回滚的操作
- 不保证一致性:既然redis不能保证一个错误全部回滚,那么就不能保证结果一定如你所料的
- 不需要隔离性:注意这里是不需要,因为Redis是单线程的不涉及隔离
- 不需要持久性:Redis数据保存在内存,是否开启持久化是redis-server的事情,跟事务无关
Redis事务本质是在服务器搞了一个“事务队列”,每次客户端在事务中进行操作,都会先把命令保存在事务队列中(不会立即执行),真正收到EXEC执行后,才会发送并执行~
事务操作
MULTI
开启一个事务.执行成功后返回OK
EXEC
真正执行事务
示例:
每次添加一个操作,都会提示"QUEUED"说明命令已经进入客户端队列了
真正执行EXEC的时候,客户端才会把上述操作发送给服务器
DISCARD
放弃当前事务,此时清空事务队列,之前的操作不执行
WATCH
在执行事务的时候,如果某个事务中修改的值被其他客户端修改了,此时就容易出现数据不一致的情况
示例:
此时客户端一开启事务,并设置key为1000
这时候开一个客户端2对key进行修改:
最后再执行客户端1的事务
发现最后key的数据是200并不是1000,~~
说明当前操作出现了数据不一致的情况,因此就算redis不保证严格的隔离性,却也至少要告诉用户,当前操作可能存在风险~~
这就引入watch了~
- 当开启事务的时候,如果对watch的key进⾏修改,就会记录当前key的"版本号".(版本号是个简单的整数,每次修改都会使版本变⼤.服务器来维护每个key的版本号情况)
- 在真正提交事务的时候,如果发现当前服务器上的key的版本号已经超过了事务开始时的版本号,就会让事务执⾏失败.(事务中的所有操作都不执⾏)
示例:
客户端1先启动事务 :
客户端2再执行:
然后执行客户端1的事务:
发现最后事务并没有成功执行,因为k1再另一个客户端被修改过了,整个事务都没有执行
UNWATCH
取消对key的操作,跟WATCH反着来就对了
主从复制
分布式系统中为了解决单点问题,通常会把数据复制多个副本部署到其他服务器,满⾜故障恢复和负载均衡等需求。Redis也是如此,它为我们提供了复制的功能,实现了相同数据的多个Redis副本。复制功能是⾼可⽤Redis的基础,哨兵和集群都是在复制的基础上构建的
配置主从复制
建立复制关系
参与复制的redis示例划分为一个主节点和多个从节点。数据流是单向的,即从节点从主节点中同步数据。并且默认设置下从节点是只读的~~(不知道配置文件在哪可以看上一篇博客)
1.在redis.conf中加入slaveof {masterHost} {masterPort}随着Redis启动生效(注意这里改的是从机的配置,主从复制主从复制,不要改主机配置,所以这个redis.conf其实就是下面的slave.conf)
1.1)复制/etc/redis/redis.conf 的文件到一个新的文件夹 并重命名为 slave1.conf~
1.2)这里关闭以守护进程的方式打开,方便后续关闭~
1.3)在配置文件的最后加入这个说明
1.4)如果跟博主一样只在一台服务器上跑多个redis,记得把从节点配置文件的port改了~
1.5)启动两个不同端口从节点
下面两种方法不做演示~~
2)在redis-server启动命令时加入 --slaveof {masterHost} {masterPort}生效
3)直接使用redis命令:{masterHost} {masterPort}生效
主从关系建立完成并开启之后,就可以指定端口连接一下看看~
观察一下主从复制能不能行,在6379端口写入,在6380读取:
info replication
通过info replication命令可以查看复制相关状态~
主节点的信息~
从节点信息:
断开复制
slaveof命令不但可以建⽴复制,还可以在从节点执⾏ slaveof no one 来断开与主节点复制关系。例如在 6380 节点上执⾏ slaveof no one 来断开复制
断开复制的主要流程为:
- 断开与主节点复制关系
- 从节点晋升成主节点
从节点断开复制后并不会抛弃原有数据,只是⽆法再获取主节点上的数据变化
通过 slaveof 命令还可以实现切主操作,将当前从节点的数据源切换到另⼀个主节点。执⾏
slaveof {newMasterIp} {newMasterPort} 命令即可
切主操作主要流程:
- 断开和旧主节点的复制关系
- 与新主节点建立复制关系
- 删除从节点当前所有数据
- 从新主节点进行复制操作
安全性
对于数据⽐较重要的节点,主节点会通过设置 requirepass 参数进⾏密码验证,这时所有的客⼾
端访问必须使⽤ auth 命令实⾏校验。从节点与主节点的复制连接是通过⼀个特殊标识的客⼾端来完成,因此需要配置从节点的masterauth 参数与主节点密码保持⼀致,这样从节点才可以正确地连接到主节点并发起复制流程。
本文并没有配置主节点密码
只读
默认情况下,从节点使⽤ slave-read-only=yes 配置为只读模式。由于复制只能从主节点到从节
点,对于从节点的任何修改主节点都⽆法感知,修改从节点会造成主从数据不⼀致。所以建议线上不要修改从节点的只读模式。
传输延迟
主从节点⼀般部署在不同机器上,复制时的⽹络延迟就成为需要考虑的问题,Redis?为我们提供
了 repl-disable-tcp-nodelay 参数⽤于控制是否关闭 TCP_NODELAY,默认为 no,即开启 tcp-nodelay 功能,说明如下:
- 当关闭时,主节点产⽣的命令数据⽆论⼤⼩都会及时地发送给从节点,这样主从之间延迟会变⼩,但增加了⽹络带宽的消耗。适⽤于主从之间的⽹络环境良好的场景,如同机房部署。
- 当开启时,主节点会合并较⼩的 TCP 数据包从⽽节省带宽。默认发送时间间隔取决于Linux 的内核,⼀般默认为 40 毫秒。这种配置节省了带宽但增⼤主从之间的延迟。适⽤于主从⽹络环境复杂的场景,如跨机房部署。
拓扑
Redis的复制拓扑结构可以⽀持单层或多层复制关系,根据拓扑复杂性可以分为以下三种:⼀主⼀从、⼀主多从、树状主从结构
简单来说,一个从节点也可以成为其他人的主节点,(你虽然是个儿子当时你也可以下个崽当爹)
一主一从结构
⼀主⼀从结构是最简单的复制拓扑结构,⽤于主节点出现宕机时从节点提供故障转移⽀持,如图
所⽰。当应⽤写命令并发量较⾼且需要持久化时,可以只在从节点上开启?AOF,这样既可以保证数据安全性同时也避免了持久化对主节点的性能⼲扰。
但是需要注意当主节点关闭持久化功能时,主节点挂了,要避免自从重启问题
一主多从结构
树形拓扑结构
原理
主从节点建立复制流程图
第一步:保存主节点(master)的信息
配置主从关系后,第一步就是保存master信息,此时info replication中就有如下信息
第二步:从节点内部通过没秒运行的定时任务维护复制相关逻辑,当定时任务发现存在新的主节点后,会场是与主节点建立基于TCP的网络来呢机,如果节点无法建立连接,定时任务会无限重试,直到成果或者用户停止
第三步:发送ping命令。连接成功之后,从节点通过ping 命令确认主节点在应⽤层上是⼯作良好的。如果ping命令的结果pong回复超时,从节点会断开TCP连接,等定时任务下次重新建⽴连接。
第四步: 权限验证。如果主节点设置了 requirepass 参数,则需要密码验证,从节点通过配置masterauth 参数来设置密码。如果验证失败,则从节点的复制将会停⽌
第五步: 同步数据集。对于⾸次建⽴复制的场景,主节点会把当前持有的所有数据全部发送给从节点,这步操作基本是耗时最⻓的,所以⼜划分称两种情况:全量同步和部分同步
第六步:命令持续复制。当从节点复制了主节点的所有数据之后,针对之后的修改命令,主节点会持续的把命令发送给从节点,从节点执⾏修改命令,保证主从数据的⼀致性
数据同步psync
语法:
PSYNC replicationid offset
- 如果 replicationid 设为 ? 并且 offset 设为 -1 此时就是在尝试进⾏全量复制
- 如果 replicationid offset 设为了具体的数值,则是尝试进⾏部分复制
replicationid/replid(复制id)
主节点的复制 id. 主节点重新启动,或者从节点晋级成主节点, 都会⽣成⼀个 replicationid. (同⼀个节点, 每次重启, ⽣成的 replicationid也会变化).
从节点和主节点建立连接之后就能看到
关于master_replid和master_replid2
- 比如当前有两个节点A和B,A是master主节点,B是slave从节点
- 此时B就会记录下A的master_replid
- 如果此时网络出现了抖动,B认为A已经挂了,那么B就会成为主节点,于是B给自己分配了一个新的master_replid给自己,将旧master_replid保存到master_replid2上
- --> 如果后续网络恢复了,B可以根据master_replid2找回之前的主节点
- --> 如果网络没有回复,B就按照新的master_replid自成一派来处理后续请求
offset(偏移量)
参与复制的主从节点都会维护⾃⾝复制偏移量。主节点(master)在处理完写⼊命令后,会把命令的字节⻓度做累加记录,统计信息在 info replication 中的 master_repl_offset 指标中。
从节点(slave)每秒钟上报⾃⾝的复制偏移量给主节点,因此主节点也会保存从节点的复制偏移量,统计指标如下
可以看出主节点此时的offset和两个从节点的offset一致,说明两个从节点数据已经完全同步
psync运行流程:
1)从节点发送 psync 命令给主节点,replid 和 offset 的默认值分别是 ? 和 -1
2)主节点根据 psync 参数和⾃⾝数据情况决定响应结果:
- 如果回复 +FULLRESYNC replid offset,则从节点需要进⾏全量复制流程。
- 如果回复 +CONTINEU,从节点进⾏部分复制流程
- 如果回复 -ERR,说明 Redis 主节点版本过低,不⽀持 psync 命令。从节点可以使⽤ sync 命令进⾏全量复制
psync一般不需要手动执行,Redis会在主从复制模式下自动调用执行
sync会阻塞redis server处理其他的请求。psync不会
全量复制
流程图
部分复制
部分复制主要是Redis针对全量复制的过⾼开销做出的⼀种优化措施
使⽤psync replicationId offset命令实现。当从节点正在复制主节点时,如果出现⽹络闪断或者命令丢失等异常情况时,从节点会向主节点要求补发丢失的命令数据,如果主节点的复制积压缓冲区存在数据则直接发送给从节点,这样就可以保持主从节点复制的⼀致性。补发的这部分数据⼀般远远⼩于全量数据,所以开销很⼩。
流程图
复制积压缓冲区
复制积压缓冲区是保存在主节点上的⼀个固定⻓度的队列,默认⼤⼩为 1MB,当主节点有连接的从节点(slave)时被创建,这时主节点(master)响应写命令时,不但会把命令发送给从节点,还会写⼊复制积压缓冲区,如图所⽰。
由于缓冲区本质上是先进先出的定⻓队列,所以能实现保存最近已复制数据的功能,⽤于部分复制和复制命令丢失的数据补救。复制缓冲区相关统计信息可以通过主节点的info replication中:
127.0.0.1:6379> info replication
# Replication
role:master
...
repl_backlog_active:1 // 开启复制缓冲区
repl_backlog_size:1048576 // 缓冲区最⼤⻓度
repl_backlog_first_byte_offset:7479 // 起始偏移量,计算当前缓冲区可⽤范围
repl_backlog_histlen:1048576 // 已保存数据的有效⻓度
如果当前从节点需要的数据,已经超出了主节点的积压缓冲区的范围,则⽆法进⾏部分复制,只能全量复制了
实时复制
主从节点在建⽴复制连接后,主节点会把⾃⼰收到的修改操作,通过tcp⻓连接的⽅式,源源不断的传输给从节点.从节点就会根据这些请求来同时修改⾃⾝的数据.从⽽保持和主节点数据的⼀致性.
这样的⻓连接,需要通过⼼跳包的⽅式来维护连接状态,这里是redis自己实现心跳机制不是TCP自带的
- 1)主从节点都有心跳检测机制,各自模拟成对方客户端进行通信
- 2)主节点默认每隔10 秒对从节点发送 ping 命令,判断从节点的存活性和连接状态
- 3)从节点默认每隔 1 秒向主节点发送 replconf ack {offset} 命令,给主节点上报⾃⾝当前的复制偏移量。
如果主节点发现从节点通信延迟超过 repl-timeout 配置的值(默认?60?秒),则判定从节点下线,断开复制客⼾端连接。从节点恢复连接后,⼼跳机制继续进⾏
总结
主从复制特点
- Redis通过复制功能实现主节点的多个副本
- 主节点用来写,从节点用来读,这样可以降低主节点的访问压力
- 复制支持多种拓扑结构~
- 复制有全量复制(开销大),部分复制(开销小),实时复制
- 主从节点之间通过心跳机制保证主从节点通信正常和数据一致性
主从复制的配置过程
主节点配置不需要改动。从节点在配置⽂件中加⼊ slaveof 主节点ip 主节点端⼝ 的形式即可.
主从复制的缺点
- 从机多了,复制数据的延时⾮常明显
- 主机挂了,从机不会升级成主机.只能通过⼈⼯⼲预的⽅式恢复(下一章哨兵能解决)