你真的懂Redis的5种基本数据结构吗?这些知识点或许你还需要看看(图文并茂,浅显易懂,建议收藏)
1052
2022-05-30
一 分布式理论基石CAP
C consistent 一致性
A availability 可用性
P Partition tolerance 分区容忍性
分布式的前提:分布式节点在不同机器上做网络隔离,意味着必然有网络断开的风险, 这种场景叫 网络分区
当网络分区时 发生网络故障时, 一致性和可用性二选一
1 分布式节点之间无法进行通信,对A 节点操作无法同步到另一个节点B,一致性无法进行满足
2 暂停服务修复 A –B 之间的通信, 这就是牺牲了可用性
最终一致性
Redis 主从数据时异步同步的,Redis在定义上不满足一致性的要求,客户端在Redis上修改数据后, 立即返回,不考虑slave是否接收到, 即使主从断开,主依旧对外提供服务。但是Redis保证最终一致性, slave在网络恢复后 采用多种策略追赶, 保持与主节点一致
二 BASE理论
BASE是对CAP中一致性和可用性权衡的结果,其来源于对大规模互联网分布式系统实践的总结,是基于CAP定律逐步演化而来。 其核心思想是即使无法做到强一致性,但每个应用都可以根据自身业务特点,采用适当的方式来使系统达到最终一致性 BASE就是为了解决关系数据库强一致性引起的问题而引起的可用性降低而提出的解决方案 BASE其实是下面三个术语的缩写: 基本可用(Basically Available): 基本可用是指分布式系统在出现故障的时候,允许损失部分可用性,即保证核心可用。 电商大促时,为了应对访问量激增,部分用户可能会被引导到降级页面,服务层也可能只提供降级服务。这就是损失部分可用性的体现。 软状态(Soft State): 软状态是指允许系统存在中间状态,而该中间状态不会影响系统整体可用性。 分布式存储中一般一份数据至少会有三个副本,允许不同节点间副本同步的延时就是软状态的体现。MySQL Replication 的异步复制也是一种体现。 最终一致性(Eventual Consistency): 最终一致性是指系统中的所有数据副本经过一定时间后,最终能够达到一致的状态。 弱一致性和强一致性相反,最终一致性是弱一致性的一种特殊情况。 它的思想是通过让系统放松对某一时刻数据一致性的要求来换取系统整体伸缩性和性能上改观。就在于大型系统往往由于地域分布和极高性能的要求,不可能采用分布式事务来完成这些指标,要想获得这些指标,我们必须采用另外一种方式来完成
Redis主从命令
配置slave redis-cli -p 6381 -a 123 SLAVEOF 127.0.0.1 6380 redis-cli -p 6382 -a 123 SLAVEOF 127.0.0.1 6380 查看master slave redis-cli -p 6382 -a 123 info replication 停止主从 SLAVEOF NO ONE redis.conf replica-priority 100 # 数字越小级别越高,越优先升级为主 旧版本slave-priority
Redis 主从原理
1 主从第一阶段 同步(psync rdb snapshot) 1.1 slave 库通过slaveof ip 6379命令,连接主库,并发送PSYNC给主库 (slave 执行psync $master_runid $slave_offset) #master_runid是主库redis实例的一个唯一标识id,是redis实例创建的时候自动生成的。offset是指从节点的复制偏移量 1.2 master收到PSYNC,会立即触发BGSAVE,后台保存RDB,发送给slave Master fork一个bgsave子进程生成一个RDB快照文件发送给从库,由slave完成加载 #主库收到这个请求后,把自己的runid和offset发送给从库 (master执行 FULLRESYNC $master_runid $master_offset) 1.3 副本库接收后会应用RDB快照 2 主从第二阶段 命令传播(commands propagation) 2.1主库只要发生新的操作,保存并发送给slave都会以命令传播的形式自动发送给副本库 2.2 所有复制相关信息,从info replication信息中都可以查到.即使重启任何节点,他的主从关系依然都在 2.3 如果发生主从关系断开时,从库数据没有任何损坏,在下次重连之后,从库发送PSYNC给主库 2.4 主库只会将从库缺失部分的数据同步给从库应用,达到快速恢复主从的目的
Redis 核心复制同步 快照同步&增量同步
1 快照同步
Master :主节点进行bgsave,将内存中数据落盘后 发送给 slave
Slave: 收到快照后进行全量加载,加载前要将自己内存数据清空, 加载完毕后通知master 进行增量同步
注意: 快照同步时,master的复制buffer不停前移,如果快照时间过长或者复制buffer过小, 会导致同步期间 复制buffer被覆盖, 导致无法进行增量复制,会再次发起快照同步,陷入死循环. 合理配置buffer参数大小 (replication buffe)
replication buffer的作用 replication buffer里面存放的数据是下面三个时间内master数据更新操作: master执行rdb bgsave产生snapshot的时间内master变更的数据 master发送rdb到slave网络传输时间内master变更的数据 slave load rdb文件把数据恢复到内存的时间内 master变更的数据 主从全量同步过程中,主库是不会阻塞的,这个时候还会继续接收新的写请求, 并写入replication buffer redis server会为每一个连接到自己的客户端创建一个replication buffer,用来缓存主库执行的命令。 等从库加载完成RDB文件后,主库就会把缓存的命令发送给从库,完成全量最终的全量同步 如果replication buffer写满了,无论客户端是普通客户端还是从库,只能断开跟这个客户端的连接了。这样从库全量同步失败,只能再次尝试全量同步 client-output-buffer-limit normal 0 0 0 client-output-buffer-limit slave 256mb 64mb 60 client-output-buffer-limit pubsub 32mb 8mb 60 client-output-buffer-limit
2 增量同步
Redis 同步的是指令流,
master: 将数据修改指令落到本地内存的buffer中, 异步将buffer同步到slave节点
slave: 执行同步过来的指令流 同时向master反馈同步的偏移量
redis从库加载完成RDB文件后,就会继续同步从库的增量写命令。如果从库的读取速度比较慢,就有可能导致从库还未读取的操作被主库新写的操作覆盖了,这会导致主从库间的数据不一致
解决方案 repl_backlog_buffer环形缓冲区 (参数 repl-backlog-size)
repl_backlog_buffer 是一个环形缓冲区,主库会记录自己写到的位置,从库则会记录自己 已经读到的位置
1 主库的写命令,除了传给从库后,还会写入repl_backlog_buffer 2 当主从断开后,重新建立连接,从库会发送之前的那个命令:psync $master_runid $offset (slave 发送slave_repl_offset 发给主库) 3 主库就会在repl_backlog_buffer中找到offset的位置,把之后的写命令写入replication buffer同步给从库 (master 判断master_repl_offset 和 slave_repl_offset 之间的差距) 4 如果repl_backlog_buffer已经能被覆盖, 则会触发快照同步
备注 所有slave从库共享一个 repl_backlog_buffer (环形结构)
其大小可以根据 估算积压缓冲区的大小repl-backlog-size值不小于这两者的乘积。 缓冲空间大小 =主库更新 命令 *((master执行rdb bgsave的时间)+ (master发送rdb到slave的时间) + (slave load rdb文件的时间) ) repl_backlog_size = 缓冲空间大小 * 2 如果主库每秒写入 2000 个操作,每个操作的大小为 2KB, 网络每秒能传输 1000 个操作,那么有1000个操作需要缓冲起来,这就至少需要 2MB 的缓冲空间。 否则,新写的命令就会覆盖掉旧操作了。为了应对可能的突发压力,把 repl_backlog_size 设为 4MB
三 Sentinel
Redis从2.8开始正式提供了Sentinel(哨兵)来解决主从切换问题;根据投票数自动将从库转换为主库, 类似zookeeper集群, 集群高可用心脏。
Sentinel 负责持续健康主节点的健康, 客户端连接集群时,会首先连接Sentinel,
通过sentinel来寻址主节点,然后再连接主节点进行数据交互, 当主down了, 客户端重新向sentinel寻址, 完成主备切换,主修复后加入集群会成为从节点
如果主从延迟较大,sentinel无法保证切换时 主从数据状态一致,但会尽可能通过配置参数来保证一致性
min-slaves-to-wirte 1 # 至少一个从节点在进行正常复制, 否则停止对外服务, 不可用 min-slaves-max-lag 10 # 10s内没有收到slave节点心跳,意味着slave节点不正常
Sentinel的使用
from redis.sentinel import Sentinel sentinel = Sentinel([('localhost', 26379)], socket_timeout=0.1) master = sentinel.master_for('mymaster', socket_timeout=0.1) slave = sentinel.slave_for ('mymaster', socket_timeout=0.1) master.set('k1','v1') slave.get('k1')
哨兵模式是一种特殊的模式,首先Redis提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行
其原理是哨兵通过发送命令,等待Redis服务器响应,从而监控运行的多个Redis实例.
哨兵作用
1通过发送命令,让Redis服务器返回监控其运行状态,包括主服务器和从服务器。
2当哨兵监测到master宕机,会自动将slave切换成master,然后通过发布订阅模式通知其他的从服务器,修改配置文件,让它们切换主机。
使用多个哨兵进行监控,各个哨兵之间还会进行监控,这样就形成了多哨兵模式。
假设主服务器宕机,哨兵1先检测到这个结果,系统并不会马上进行failover过程,仅仅是哨兵1主观的认为主服务器不可用,这个现象称为主观下线。
当后面的哨兵也检测到主服务器不可用,并且数量达到一定值时,那么哨兵之间就会进行一次投票,投票的结果由一个哨兵发起,进行failover[故障转移]操作。
切换成功后,就会通过发布订阅模式,让各个哨兵把自己监控的从服务器实现切换主机,这个过程称为客观下线
哨兵配置 & 启动
Redis-sentinel /myredis/sentinel.conf
# Example sentinel.conf port 26379 # 哨兵sentinel实例运行的端口 默认26379 dir /tmp # 哨兵sentinel的工作目录 # 哨兵sentinel监控的redis主节点的 ip port # master-name 可以自己命名的主节点名字 只能由字母A-z、数字0-9 、这三个字符".-_"组成。 # quorum 配置多少个sentinel哨兵统一认为master主节点失联 那么这时客观上认为主节点失联了 # sentinel monitor
private static JedisSentinelPool jedisSentinelPool=null; public static Jedis getJedisFromSentinel(){ if(jedisSentinelPool==null){ Set
# SCRIPTS EXECUTION #配置当某一事件发生时所需要执行的脚本,可以通过脚本来通知管理员,例如当系统运行不正常时发邮件通知相关人员。 #对于脚本的运行结果有以下规则: #若脚本执行后返回1,那么该脚本稍后将会被再次执行,重复次数目前默认为10 #若脚本执行后返回2,或者比2更高的一个返回值,脚本将不会重复执行。 #如果脚本在执行过程中由于收到系统中断信号被终止了,则同返回值为1时的行为相同。 #一个脚本的最大执行时间为60s,如果超过这个时间,脚本将会被一个SIGKILL信号终止,之后重新执行。 #通知型脚本:当sentinel有任何警告级别的事件发生时(比如说redis实例的主观失效和客观失效等 等),将会去调用这个脚本,这时这个脚本应该通过邮件,SMS等方式去通知系统管理员关于系统不正常运行的信息。 #调用该脚本时,将传给脚本两个参数,一个是事件的类型,一个是事件的描述。如果sentinel.conf配置文件中配置了这个脚本路径,那么必须保证这个脚本存在于这个路径,并且是可执行的,否则sentinel无法正常启动成功。 #通知脚本 # sentinel notification-script
drop external table ext_redisparam_info CREATE EXTERNAL TABLE ext_redisparam_info (like sor.redisparam_info) LOCATION ( 'gpfdist://******:8100/redisParm.csv' ) FORMAT 'text' (delimiter E'|' null E'\\N' escape E'\\') SEGMENT REJECT LIMIT 1000 ROWS select *,round(t.diff/1024.0,2) as kb,round(t.diff/1024.0/1024.0,2) mb from( select *, param_value::bigint -( lead( param_value::bigint ) over( order by evt_timestamp desc )) as diff from sor.redisparam_info where port = '6384' ) t
Redis 分布式
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。