各种集群(mysql,redis,mq)节点之间的数据同步以及微服务分布式的笔记问题

1.mysql主从同步原理

主从配置教程参考
relay-log(中继日志)
1.在主库上开启记录二进制日志。在每次准备提交事务完成数据更新前,主库将数据更新的事件记录到二进制日志中。MySQL会按事务提交的顺序而非每条语句的执行顺序来记录二进制日志。在记录二进制日志后,主库会告诉存储引擎可以提交事务了。
2.备库将主库的二进制日志复制到其本地的中继日志中。首先,备库会启动一个工作线程,称为I/O线程,I/O线程跟主库建立一个普通的客户端连接,然后在主库上启动一个特殊的二进制转储(binlog dump)线程(该线程没有对应的SQL命令),这个二进制转储线程会读取主库上二进制日志中的事件。它不会对事件进行轮询。如果该线程追赶上了主库,它将进入睡眠状态,直到主库发送信号量通知其有新的事件产生时才会被唤醒,备库I/0线程会将接收到的事件记录到中继日志中。
3.备库的SQL线程执行最后一步,该线程从中继日志中读取事件并在备库执行,从而实现备库数据的更新。当SQL线程追赶上I/O线程时,中继日志通常已经在系统缓存中,所以中继日志的开销很低。SQL线程执行的事件也可以通过配置选项来决定是否写入其自己的二进制日志中,它对于我们稍后提到的场景非常有用。

如图:
在这里插入图片描述

2.redis主从节点和槽节点之间的通信

主从节点之间的数据就是备份的,但是槽节点不是,redis集群对外工作是多个主节点一起对外的,一旦有一个挂了就整个服务集群挂了。
在这里插入图片描述

主节点1给主节点2和主节点3发信息,3主节点没回信息判定下线,这时候主节点也会发,没回判定下线,超过一半主节点的下线就认为故障,主节点3的从节点就会顶上成为主节点:
在这里插入图片描述

Redis 集群是由各个节点各自为一个集群的(也就是主从节点),通过执行 CLUSTER MEET 目标机IP 目标机端口 命令,使得两台机器建立连接,从而构成集群。这是通过套接字直接通信的。整个集群对应的槽是由 16384 大小的二进制数组组成,集群中每个主节点分配一部分槽。set key1 value1 命令时用CRC16(key1) & 16383 =与运算结果,结果就是确认在那个槽位就确认在哪个主节点。

主从节点之间通信是通过从节点执行slaveof master_ip port,建立关系的,数据备份流程图:在这里插入图片描述

主服务器和从服务器都维护着一个执行命令的偏移量;同步过程断线了,重连之后会从偏移那段开始。

3.rocketmq的网络模型和各部分通信

参考
1.nameserver集群:保存路由,topic,Broker等信息,每个节点都是有完整的数据,且和每一个broker节点都保持联系,所以nameserver节点之间是相互独立,没有数据同步,一个挂了不会有任何影响。
2.broker集群:工作包括接收 Producer 发过来的消息、处理 Consumer 的消费消息请求、消息的持 久化存储、消息的 HA 机制以及服务端过滤功能等 。每个broker是主从模式,每个 Broker 节点(从节点也是)都要跟所有的 Name Server 节点建立长连接,定义注册 Topic 路由信息和发送心跳。发送心跳是为了判定broker是否在线。
3.producer:
4.consumer:与某一个nameserver保持长链接,每隔30s拉去一次topic的队列最新信息
与所有的broker保持长链接每隔30s发送一次心跳给broker,每个broker会每隔10s去扫一次全部消费者心跳,超时会认为断开与消费者的联系

4.producer:
与nameserver:
单个生产者者和一台nameserver保持长连接, 定时查询topic配置信息,如果该nameserver挂掉,生产者会自动连接下一个nameserver,直到有可用连接为止,并能自动重连。
默认情况下,生产者 每隔30秒从nameserver获取所有topic的最新队列情况,这意味着某个broker如果宕机, 生产者最多要30秒才能感知。与nameserver没有心跳
与broker:
生产者每30秒从Nameserver获取Topic跟Broker的映射关系,更新到本地内存中。再跟Topic涉及的所有Broker建立长连接,每隔30秒发一次心跳。在Broker端也会每10秒扫描一次当前注册的Producer,如果发现某个Producer超过2分钟都没有发心跳,则断开连接
在这里插入图片描述

在这里插入图片描述

问题一:broker主节点挂了怎么办

由于消息分布在各个broker上,一旦某个broker宕机,则该broker上的消息读写都会受到影响。所以rocketmq提供了master/slave的结构,**salve定时从master同步数据,如果master宕机,则slave提供消费服务,但是不能写入消息,

问题二:消费是如何消费的??

通过消费者的本地队列进行来解耦; 消费者不间断的从broker拉取消息,消息拉取到本地队列,然后本地消费线程消费本地消息队列,只是一个异步过程,拉取线程不会等待本地消费线程,这种模式 实时性非常高(本地消息队列达到解耦的效果,响应时间减少)。对消费者对本地队列有一个保护,因此本地消息队列不能无限大,否则可能会占用大量内存,本地队列大小由DefaultMQPushConsumer的pullThresholdForQueue属性控制,默认1000,可手动设置。

问题三:如果一个topic在某broker上有3个队列,一个消费者消费这3个队列,那么该消费者和这个broker有几个连接?

答案是一个连接,消费单位与队列相关,消费连接只跟broker相关,事实上,消费者将所有队列的消息拉取任务放到本地的队列,挨个拉取,拉取完毕后,又将拉取任务放到队尾,然后执行下一个拉取任务。

问题四:broker的同步复制和异步复制?

如果一个 Broker组有 Master和 Slave, 消息需要从 Master复制到 Slave上。主从同步是指同步commitlog文件,同步由名字为HAservice的服务完成。HAservice包括server端HA(high availability 高可用的意思),客户端以及一些维护线程,从节点的 HAClient 中的,该client启动起来之后,会一直不停地轮询向master请求新的数据,然后同步到自己的commitlog中。
同步复制方式:
Master 和 Slave 均写成功 后才反馈给客户端写成功状态

异步复制方式:
只要 Master 写成功即可反馈给客户端写成功状态 。
在这里插入图片描述
主Broker向从Broker发送消息的时候都会带上物理偏移量。从Broker接收消息并读取物理偏移量,并与其本地的物理偏移量进行比较,如果相等则存储并继续与主Broker进行通信。如果不相等,则表示主从复制出现了混乱,此时会主动断开与主Broker之间的TCP连接,重新建立一条TCP连接,再次开始主从复制。
使用原生Java NIO网络通信编程

问题五:messegeQueue和consumerQueue区别

rocketmq 默认会给每个 topic 创建4个队列,每个队列有一个 queuelog,也就是ConsumeQueue
每个topic可能在多个broker下有多个消息的队列,这个队列叫messegeQueue,这个只是一个概念,不知实实在在的对象存在;
MessageQueue会有多个ConsumeQueue文件,底层储存跟CommitLog一样使用MappedFile,每个CQUnit的大小是固定的,存储了消息的offset、消息size和tagCode

在这里插入图片描述

问题六:什么是processQueue

ProcessQueue就是消费者本地队列,和一个MessageQueue是对应的,MessageQueue用来表示拉取回来的消息元数据信息:topic、brokerName、queueId。消息拉取的时候,会将实际消息体、拉取相关的操作存放在其中。比如消费进度,消费等等功能的底层核心数据保存都是有ProcessQueue提供

问题七:什么是延迟队列?

存储制定延迟到特定时间才被消费消息的队列叫做延迟队列。延迟消息发送到broker后不会立刻投递到某个topic,而是放到延迟队列,到了时间再投递。可以指定:1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m,8m 9m 10m 20m 30m 1h 2h”。

问题八:rocketmq如何保证顺序消费?

顺序消息分为全局顺序消息与部分顺序消息,全局顺序是指某个Topic下的所有消息都要保证顺序;部分顺序消息只要保证每一组消息被顺序消费即可。如果想要实现全局顺序消息,那么只能使用一个队列,以及单个生产者,这是会严重影响性能。因此,我们常说的顺序消息通常是只的部分顺序消息。什么叫每一组消息?这是一个业务概念,例如订单创建,订单付款,订单完成这三个个消息组成一组,但是必须是按顺序的。我们讨论有序就是讨论这个问题。
顺序消费实际上有两个核心点,一个是生产者有序存储,另一个是消费者有序消费。
生产者有序存储:
因为RocketMQ支持生产者在投放消息的时候自定义投放策略,我们实现一个MessageQueueSelector接口,使用Hash取模法来保证同一个订单在同一个队列中就行了,即通过订单ID%队列数量得到该ID的订单所投放的队列在队列列表中的索引,然后该订单的所有消息都会被投放到这个队列中。(这个队列是某一个broker的某一个队列,但是broker挂了可能就丢失了)

消费者有序消费:
为什么会消费没有按顺序消费的问题?因为1.要保证一组消息全部被消费组某一个消费者消费,2.消费端拉去消息是按顺序的,顺序放在本地队列中,但是消费本地队列中的消息是线程池并发的,哪个先后无法控制。消费端可以通过MessageListener这个参数指定是否需要保证顺序消费。解决以上两个问题需要三个锁:参考
1.broker端的分布式锁:能确保某一组消息被一个消费组下某一个消费者消费
2.本地synchronized锁:保证同一时刻对于同一个队列只有一个线程去消费它。
3.本地consumeLock锁:负载均衡时,如果某个队列C被分配给了新的消费者,那么当前客户端消费者需要对broker的分布式锁释放,broker端的分布式锁被释放了,那就会出现重新分配的情况,解决这种情况设计是:ProcessQueue的本地consumeLock。只有获取了这个锁,才能尝试请求broker端对该messageQueue的分布式锁解锁

问题九:mq的消息堆积如何处理

什么原因会造成消息堆积?:
消费端:
1.新上线的消费者功能有BUG,消息无法被消费
2.消费者实例宕机或因网络问题暂时无法同Broker建立连接。
生产端:
3.生产者短时间内推送大量消息至Broker,消费者消费能力不足
4.生产者未感知Broker消费堆积持续向Broker推送消息。

处理方法:
1.灰度发布,tips验收环境下测试上线的消费端是不是有bug
2.新增消费服务,增加消费力
3.消息端消费本地队列的线程数设置大一点,提高消费并发度
4.业务上把消费改成批量方式消费,单个消费的改成批量的,减少消息的个数

问题10:最终没消费的消息会怎么办?

commitlog文件存在一个过期时间,默认为72小时,即三天。除了用户手动清理外,在以下情况下也会被自动清理,无论文件中的消息是否被消费过
1.文件过期,且到达清理时间点(默认为凌晨4点)后,自动清理过期文件
2.文件过期,且磁盘空间占用率已达过期清理警戒线(默认75%)后,无论是否达到清理时间点,都会自动清理过期文件

问题十一:如何实现熔断??

答:被调用方下游没有响应,就向调用方上游直接返回一个错误响应即可,而不是长时间的等待,这样避免调用时因为等待而线程一直得不到解放,避免故障在分布式系统中蔓延。实现熔断的有Spring cloud的Hystrix,在k8s中istio也可以实现熔断。(isolate IO的缩写)实践可参考istio实践参考

问题十二:mq重复消费的原因和解决方案

rocketmq出现消息重复消费的原因是因为网络抖动不稳定的原因,可能是发送端发送重复了也可能是消费端拉去数据的时候拉重复了,重复的消息的messageId是相同的。
解决方案:
1.redis加锁messageId加锁
2.或者业务上利用数据库有条件的插入语句限制重复插入。

问题十三:mq如何保证消费成功?

rocketmq是采用ACK确认机制的,只有消费端消费完之后返回成功的确认了才会认为消费成功,一直失败会一直重试,默认重试到16次就认为有问题把消息放入死信队列,需要做人工干预。

问题十四:mq的半消息机制实现分布式事务

broker有个队列叫半消息队列,用来存半消息(事务消息),第一次发送信息来不会立刻投递到对应的topic消息队列里,而是等收到发送端对应的消息的确认之后才会选择投降或放弃投递,并且mq还会定时查询半消息队列,没收到确认的消息会对发送端进行反查询机制。
这种机制可以用于分布式事务,把发送mq放入到发送端的事务中,半消息的发送和发送端的本地事务是保证了的原子性的,事务提交就投递到topic,没提交或者会滚就不投递。但是投递完后的消费可能会失败,这是无法保证的,因为mq是保证消费成功的,消费没成功的会在死信队列,这是需要人工处理的,这种机制比http直接上下游的调用上游再提交事务更可靠。
具体的mq实现分布式流程图如下:
参考
在这里插入图片描述
为什么需要进行半消息的预选提交返回确认,进行连接,不直接上游事务提交完成后进行mq的发送呢?
可以确保消息发送到broker成功后再执行本地事务,直接发送的话会一样存在http直接请求下游的问题,mq发送返回成功,但是可能因为网络的原因发送失败了,但是上游本地事务已经提交了,mq发送返回失败,但是可能因为超时实际上已经发送落到broker了,但是上游的事务已经回滚。半消息机制可以把发送到broker和提交本地事务保证原子性

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值