MQ
1. 为什么使用消息队列?
引入MQ主要作用异步、解耦、削峰。异步:完单通知清结算;记录商户动作到日志表;接单绑定虚拟号;下单通知匹配、风控;支付成功回调;解耦:行程/支付单状态并更,通知其他系统进行操作。如通知营销(多单任务,策略触发)、业务层、特征平台、租赁平台、会员、政府对接、奖励金、判责、风控、司乘安全、开放平台。削峰:用车高峰(大促、每日高峰期);定时催收; 引入MQ带来的问题,系统可用性降低——MQ挂了;复杂度提高——重复消费、消息丢失;一致性问题——A系统消费完操作了,B消费完没操作。
2. 如何保证消息队列的高可用?
消息队列保证高可用是靠 主从同步+故障转移 来做到的。 RocketMQ:主从节点使用相同cluster名字注册在相同nameServer上,brokerId小的为主节点。一方面,有消息进来,主节点会主动通知从节点,从节点ack了告诉生产者发送成功。另一方面,从节点主动向主节点建立tcp连接,每5s发送commitLog文件最大偏移量,来拉取还未同步的消息。拉取到后更新从的offset。通过开启dledger配置,来进行故障转移,自动选主。Kafka:通过zk选举一个broker做为controller,broker启动时向zk创建临时节点/controller,优先创建成功的broker节点就是controller。如果该节点挂掉,zk上的临时节点就会消失,通过watch机制,其他节点会重新创建/controller节点争夺controller权力。controller borker会管理broker/topic/partition信息,和partition主从选举。partition主从选举采用类似PacificA算法,默认让ISR中第一个replica变成leader。leader选好后,客户端只能通过leader进行读写操作。主从同步,follower会向leader发送一个fetch请求,leader发送数据后,follower写入数据并更新自己的leo(log end offset),主节点更新HW(High WaterMark)——最小leo。故障转移,follower故障,恢复后把HW之后数据截掉,重新同步;leader故障,replica1变成leader。其他follwer都把高于HW的截掉,重新同步。
3. 如何保证消息不被重复消费?
消费者做幂等,具体场景具体分析。比如订单变更消息,根据发来的状态,查看库里当前状态,如果状态一样不做操作。4. 如何保证消息的可靠性传输?producer/broker/consumer 两个维度来看。producer发送消息到broker,broker会ack。根据配置状态的不同,可以立马ack,半数以上follower写入ack,全部节点写入ack。不然就重试,可以配置重试次数。broker消息持久化。consumer处理完事件如果异常就不要提交。5.如何保证消费的顺序性?单线程发送,单线程消费。根据业务场景,多建几个queue,顺序发送,Aqueue处理完发Bqueue。6.如何解决消息积压?先紧急扩容,再排查原因。生产者有没有在重复发送消息?Broker机器性能是否出现瓶颈?消费者是不是有bug没有ACK,还是因为机器太少?7.如何设计消息队列?考虑水平扩容,数据分片,topic->partition,partiton迁移。持久化,落磁盘还是DB。可用性,主从复制,故障转移。数据0丢失,producer全ack? kafka1. kafka 发送消息过程?消息经过ProducerInterceptor,序列化器Serializer,分区器Partitioner后放到batches中(chm),一个分区对应一个batches。batches满了,会有Sender线程批量发送到Broker。Broker写入partition,同步给replica,完成后发送ack给producer。2. kafka和zk的关系?利用zk的有序节点、临时节点、监听机制。zk帮kafka做了 配置中心(管理Broker,Topic,Partition,Consumer信息,包括元数据变动)、负载均衡、命名服务、分布式通知、集群管理、选举、分布式锁。
4. kafka数据存储?
topic名字/partition-x/segement[index,timeindex,log]索引index是稀疏索引,默认满4k消息,记录一个索引。查找数据过程:二分查找从segement查找指定的索引文件索引文件里再二分查找,查到最近offset对应位置到对应log文件的offset附近里找消息4. 主从同步
5. offset维护早期是维护在zk,
但这样的开销太大了。后来放在一个特殊的topic————__consumer_offsets,默认50个分区,1replication。RocketMQ1. 如何保证一致性?producer发送消息,如果没有ack消息,则重试;RockerMQ事务,1.半消息 2.Broker消息回查1、生产者向Broker发送消息(半消息)2、MQ服务端将消息持久化成功后,向发送方ack确认消息已经发送成功,此时消息为半消息。3、发送方开始执行本地数据库事务逻辑4、发送方根据本地数据库事务执行结果向mq提交二次确认commit/rollback,mq收到后把消息状态修改为改投递或删除5、如果断网或特殊情况,一定时间没有收到二次确认消息, broker进行回查。默认回查15次,第一次6s,后续间隔60sconsumer在处理完成才进行ack。2.nameserver工作原理Broker与每个nameServer都会建立TCP长链接,每30s发送自己的心跳。nameServer每10s回轮询查询所有broker最近一次心跳发送时间,如果超过120s没有心跳,则认为broker挂掉了。将其移除。没用zk,是因为只需保持最终一致性,不依赖其他中间件也能减少维护成本。CAP: 一致性、可用性、分区容错性,zk是CP,nameserver是AP3.nameserver如何保证注册信息一致?nameservier互相不通信。服务注册:Broker每30s向所有nameserver发送心跳信息。服务剔除:Broker正常关闭,netty关闭监听会感知到,把服务剔除。Broker异常关闭,nameserver10s一轮询,剔除无用broker。路由发现:生产者:发送第一条消息时,会从nameserver找到topic路由信息消费者:一般订阅固定Topic,在启动时获取Broker信息。如果Broker信息发生变化,需要消费者、生产者定期更新信息。每30s获取一次。如果nameserver都挂了,有本地缓存。 4. consumer pull/push?pull 采用了长轮询。push 是注册了个listener监听消息变化,实际是封装了pull的模式,消息存在阻塞队列里。 5. mq延迟队列?producer要将一个延迟消息发送到某topicBroker判断是个延迟消息,通过临时延迟topic存储进行暂存Broker内部通过延迟服务查询消息是否到期,到期投递到对应topic消费者消费延迟投递的消息6. broker存储结构消息发送到broker时,写入commitlog,同时把commitlog中最新的offset(异步)写入consumerqueue中。consumerqueue是索引,读的时候先读索引,再找commitlog里的内容。index文件是hash结构。mmap内存映射,比较快。数据都存在commitlog,顺序读取。 7. 4.5后主从切换dledger 实现了commitlog日志的最终一致性,进行自主选举。简化的raft协议。8. commitlog中的消息结构
ES1. ES分布式架构的原理是什么?ES是底层基于lucene的集群。数据分片-es基本单位是索引,索引可以分为多个shard,一个shard是primary shard负责写入读取,其他的是replica shard,可以进行读取。支持横向扩展,提高吞吐量。故障转移-master宕机了,选举一个新master,master负责维护索引元数据,切换primary shard;非master节点宕机了,会把自身的primary shard的身份转移到其他replica shard上。2. ES写入数据的工作原理?客户端选择一个node发送请求,node根据hash找到primary shard所在的node,把请求转发,primary shard所在的node会写入buffer,buffer时是不可搜索的,1s一次refresh到os cache->segement file。同步给其他replica shard,都同步好了,返回客户端ack给客户端。3. 十亿级别如何提高查询效率?增大filesystem cache数据预热,热点数据定时查询冷热分离,高频访问的建一个索引,低频的建一个document模型设计分页性能优化——不许深度分页4. 倒排索引?由文档中所有不重复词的列表构成,对于其中每个词,有一个包含它的文档列表。TermIndex存下一些前缀和Term Dictionary的block之间的映射关系,再通过FTS压缩技术将term index缓存在内存中。term dictionary再找到对应的posting list。每个field都有posting list。是个int数组,记录了符合条件的term的documentid。postinglist会使用Frame Of Reference(索引桢)进行压缩,所有文档分成很多block,一个block存放256文档。Header放需要多少位来保存每个id,id列表是一个增量列表(id - preId)。
- es过滤器<4096 用short数组保存>4096 用bitmap 咆哮位图缓存的,高十六位找到对应的block块,用两个字节表示(高十六位/65535, 低16位%65535 )
- 倒排索引如何做联合索引?倒排索引做联合索引,形成一个跳表,最短的倒排表逐个找和另外倒排表是否存在相同元素。取交集。7. es并发控制基于乐观锁做版本控制,6.7以后不可以自己做,只能es来做。8. 深分页问题es查询都会返回一个scroll_id当游标,用游标往下查,直到hit=0缓存1. 在项目中缓存是如何使用的?缓存使用不当会造成什么后果?项目中查询接口大部分都使用到了缓存,因为是面向c端的接口,不使用缓存数据库容易被打挂。像行程单、大众评审、热路图都使用到了缓存。缓存使用不当,会出现缓存与数据库不一致、雪崩穿透击穿、并发竞争。2. Redis的线程模型
限流熔断限流作用:瞬时流量、恶意请求限流算法:计数器、滑动窗口、漏桶、令牌桶限流维度:APP/入口/ip限流策略:直接拒绝、预热、匀速排队若有收获,就点个赞吧