30分钟带你了解「消息中间件」Kafka、RocketMQ
消息中间件的应用场景
- 异步解耦
- 削峰填谷
- 顺序收发
- 分布式事务一致性
腾讯应用案例:
主流 MQ 框架及对比
说明
- Kafka:整个行业应用广泛
- RocketMQ:阿里,从 apache 孵化
- Pulsar:雅虎开源,符合云原生架构的消息队列,社区活跃
- RabbitMQ 架构比较老,AMQP并没有在主流的 MQ 得到支持
- NSQ:内存型,不是最优选择
- ActiveMQ、ZeroMQ 可忽略
Kafka 优点
- 非常成熟,生态丰富,与 Hadoop 连接紧密
- 吞吐非常高,可用性高
- sharding
- 提升 replication 速度
- 主要功能:pub-sub,压缩支持良好
- 可按照 at least once, at most once 进行配置使用,exactly once 需要 Consumer 配合
- 集群部署简单,但 controller 逻辑很复杂,实现partition 的多副本、数据一致性
- controller 依赖 ZooKeeper
- 异步刷磁盘(除了钱的业务,很少有同步 flush 的需求)
Kafka 缺点
- 写入延时稳定性问题,partition 很多时
- Kafka 通常用机械盘,随机写造成吞吐下降和延时上升
- 100ms ~ 500ms
- 运维的复杂性
- 单机故障后补充副本
- 数据迁移
- 快手的优化:迁移 partition 时旧数据不动,新数据写入新 partition 一定时间后直接切换
RocketMQ
- 阿里根据 Kafka 改造适应电商等在线业务场景
- 以牺牲性能为代价增强功能
- 按 key 对消息查询,维护 hash 表,影响 io
- 为了在多 shard 场景下保证写入延迟稳定,在 broker 级别将所有 shard 当前写入的数据放入一个文件,形成 commitlog list,放若干个 index 文件维护逻辑 topic 信息,造成更多的随机读
- 没有中心管理节点,现在看起来并没有什么用,元数据并不多
- 高精度的延迟消息(快手已支持秒级精度的延迟消息)
Pulsar
- 存储、计算分离,方便扩容
- 存储:bookkeeper
- MQ逻辑:无状态的 broker 处理
发展趋势
- 云原生
- 批流一体:跑任务时,需要先把 Kafka 数据→HDFS,资源消耗大。如果本来就存在 HDFS,能节省很大资源
- Serverless
各公司发展
- 快手:Kafka
- 所有场景均在使用
- 特殊形态的读写分离
- 数据实时消费到 HDFS
- 在有明显 lag 的 consumer 读取时,broker 把请求从本地磁盘转发的 HDFS
- 不会因为有 lag 的 consumer 对日常读写造成明显的磁盘随机读写
- 由于自己改造,社区新功能引入困难
- 阿里巴巴:开源 RocketMQ
- 字节跳动
- 在线场景:NSQ→RocketMQ
- 离线场景:Kafka→自研的存储计算分类的 BMQ(协议层直接兼容Kafka,用户可以不换 client)
- 百度:自研的 BigPipe,不怎么样
- 美团:Kafka 架构基础上用 Java 进行重构,内部叫 Mafka
- 腾讯:部分使用了自研的 PhxQueue,底层是 KV 系统
- 滴滴:DDMQ
- 对 RocketMQ 和 Kafka 进行封装
- 多机房数据一致性可能有问题
- 小米:自研 Talos
- 架构类似 pulsar,存储是 HDFS,读场景有优化
Kafka
- Kafka官网:https://kafka.apache.org/documentation/#uses
- 最新版本:2.7
Kafka 是什么?
- 开源的消息引擎系统(消息队列/消息中间件)
- 分布式流处理平台
- 发布/订阅模型
- 削峰填谷
Kafka 术语
- Topic:发布订阅的主题
- Producer:向Topic发布消息的客户端
- Consumer:消费者
- Consumer Group:消费者组,多个消费者共同组成一个组
- Broker:Kafka的服务进程
- Replication:备份,相同数据拷贝到多台机器
- Leader Replica
- Follower Replica,不与外界交互
- Partition:分区,解决伸缩性问题,多个Partition组成一个Topic
- Segment:partition 由多个 segment 组成
Kafka 如何持久化?
- 消息日志(Log)保存数据,磁盘追加写(Append-only)
- 避免缓慢的随机I/O操作
- 高吞吐
- 定期删除消息(日志段)
Kafka 文件存储机制
https://www.open-open.com/lib/view/open1421150566328.html
- 每个 partition 相当于一个巨型文件→多个大小相等 segment 数据文件中
- 每个 partition 只需要顺序读写就行了,segment 文件生命周期由配置决定
- segment file 组成:
- index file:索引文件
- data file:数据文件
- segment file 文件命名规则:
- 全局第一个 segment 是 0
- 后序每个加上全局 partition 的最大 offset
一对 segment file
message 物理结构
分区
为什么分区?
- Kafka的消息组织方式:主题-分区-消息
- 一条消息,仅存在某一个分区中
- 提高伸缩性,不同分区可以放到不同机器,读写操作也是以分区粒度
分区策略?
- 轮询
- 随机
- 按 key 保序,单分区有序
Kafka 是否会消息丢失?
- 只对“已提交”的消息做有限度的持久化保证
- 已提交的消息:消息写入日志文件
- 有限度的持久化保证:N个 broker 至少一个存活
- 生产者丢失数据
- producer.send(msg) 异步发送消息,不保证数据到达Kafka
- producer.send(msg, callback) 判断回调
- 消费者程序丢失数据
- 应该「先消费消息,后更新位移的顺序」
- 新问题:消息的重复处理
- 多线程异步处理消息,Consumer不要开启自动提交位移,应用程序手动提交位移
控制器
- 在 ZooKeeper帮助下管理和协调整个 Kafka 集群
- 运行过程中,只能有一个 Broker 成为控制器
控制器如何选举?
在 ZooKeeper 创建 /controller 节点,第一个创建成功的 Broker 被指定为控制器。
控制器有什么用?
- 主题管理(创建、删除、增加分区)
- 分区重分配
- 领导者选举
- 集群成员管理(新增 Broker、Broker 主动关闭、Broker 宕机)(ZooKeeper 临时节点)
- 数据服务:最全的集群元数据信息
控制器故障转移
- 只有一个 Broker 当控制器,单点失效,立即启用备用控制器
Kafka 的 ZooKeeper 存储结构
分布式事务的应用场景
- 团队内部,某些操作要同时更新多个数据源
- 业务团队 A 完成某个操作后,B 业务的某个操作也必须完成,A 业务并不能直接访问 B 的数据库
- 公司之间,用户付款后,支付系统(支付宝/微信)必须通知商家的系统更新订单状态
两阶段最终一致
- 先完成数据源 A 的事务(一阶段)
- 成功后通过某种机制,保证数据源 B 的事务(二阶段)也一定最终完成
- 不成功,会不断重试直到成功为止
- 或达到一定重试次数后停止(配合对账、人工处理)
如何保证最终一致?
为了保证最终一致,消息系统和业务程序需要保证:
- 消息发送的一致性:消息发送时,一阶段事务和消息发送必须同时成功或失败
- 消息存储不丢失:消息发送成功后,到消息被成功消费前,消息服务器(broker)必须存储好消息,保证发生故障时,消息不丢失
- 消费者不丢失消息:处理失败不丢弃,重试直到成功为止
消息发送的一致性如何保证?
目标
:本地事务、消息发送必须同时成功/失败
问题
- 先执行本地事务,再发送消息,消息可能发送失败
- 可把失败的消息放入内存,稍后重试,但成功率也无法达到 100%
解决方案`* 先发送半消息(Half Msg,类似 Prepare 操作),不会投递给消费者
- 半消息发送成功,再执行 DB 操作
- DB 操作执行成功后,提交半消息
发送异常会如何?
- 1 异常,半消息发送失败,本地 DB 没有执行,整个操作失败,DB/消息的状态一致(都没有提交)
- 2 异常/超时
- 生产者以为失败了,不执行 DB
- broker 存储半消息成功,等不到后序操作,会询问生产者是提交还是回滚(第6步)
- 3 DB操作失败:生产者在第 4 步告知 broker 回滚半消息
- 4 提交/回滚半消息失败:broker 等不到这个操作,触发回查(第 6 步)
- 5、6、7回查失败:RocketMQ 最多回查 15 次
代码、思维导图笔记链接
代码和思维导图在 GitHub 项目中,欢迎大家 star!
coding 笔记、点滴记录,以后的文章也会同步到公众号(Coding Insight)中,希望大家关注_
30分钟带你了解「消息中间件」Kafka、RocketMQ的更多相关文章
- 把虚拟教练带回家,「EuMotus」想用AI实现高精度运动反馈系统
https://36kr.com/p/5089139.html 无需穿戴设备,只需一个红外摄像头和+已安装好EuMotus专利软件的手提电脑 由政府主导的高达2200亿美金的健身与运动支出,15%的健 ...
- 30分钟带你了解Docker
最近一直在忙项目,不知不觉2个多月没有更新博客了.正好自学了几天docker就干脆总结一下,也顺带增加一篇<30分钟入门系列>.网上能够查到的对于docker的定义我就不再重复了,说说我自 ...
- 30分钟带你快速入门MySQL教程
这是一篇真正适合初学者的MySQL数据库入门文章,哪怕你从来没有接触过数据库,或者说你从来没有听说过有数据库这东西,请一定要相信我,我当时就是这么过来的. 如果你刚开始接触MySQL数据库,或者你需要 ...
- 30分钟带你理解 Raft 算法
为什么需要 Raft? Raft 是什么? Raft 的目标 前置条件:复制状态机 Raft 基础 Leader 选举(选举安全特性) 日志复制(Leader只附加.日志匹配) 安全 学习资料 使用 ...
- 30分钟带你了解Springboot与Mybatis整合最佳实践
前言:Springboot怎么使用想必也无需我多言,Mybitas作为实用性极强的ORM框架也深受广大开发人员喜爱,有关如何整合它们的文章在网络上随处可见.但是今天我会从实战的角度出发,谈谈我对二者结 ...
- 30分钟 带你浅入seajs源码
上个星期写了浅入requirejs的, 大家都知道 require是AMD规范(Asynchronous Module Definition) 来 今天我们一起看看 CMD规范(Common Mo ...
- 30分钟 带你浅入requirejs源码
因为最近项目想现实一个单页功能,用的是react ,然后看了一下react route,挖槽 gzip后16k? 然后我简单写了一个纯单页(不支持多页的单页,所有入口都经过rewrite跑到index ...
- 【视频】谷歌大佬30分钟让你入门机器学习(2019谷歌I/O资源分享)
如果你是个谷粉,就一定会知道: 谷歌向来都很大胆.当所有的科技公司都在讲产品.讲利润的时候,2019年的谷歌开发者大会的主题却是:人文关怀.要知道,这是政府操心的事,而不是一家公司的任务. 谷歌敢这样 ...
- 面试都在问的「微服务」「RPC」「服务治理」「下一代微服务」一文带你彻底搞懂!
❝ 文章每周持续更新,各位的「三连」是对我最大的肯定.可以微信搜索公众号「 后端技术学堂 」第一时间阅读(一般比博客早更新一到两篇) ❞ 单体式应用程序 与微服务相对的另一个概念是传统的「单体式应用程 ...
随机推荐
- EF中使用UnitOfWork
前言 关于EF5中使用UnitWork,参见另一博文: https://www.cnblogs.com/masonblog/p/9801162.html 每次提交数据库都会打开一个连接,造成结果是: ...
- java 多线程40个问题汇总(转)
java 多线程40个问题汇总,自己也记录一份,如有侵权,联系删除 ref from :http://www.cnblogs.com/xrq730/p/5060921.html 1.多线程作用 - 利 ...
- 在ubuntu上利用科大讯飞的SDK实现语音识别-语义识别等功能
首先,参考科大讯飞的官方sdk中的案例,实现和机器的日常对话和控制. 具体步骤: 1. 通过麦克风捕获说话的声音,然后通过在线语音识别获取语音中的字符. 2. 将获取到的字符上传到科大讯飞的语义识别中 ...
- 嵌入式LInux-让开发板访问外网-ping bad address baidu.com
我的嵌入式设备已经接入网络.能够ping局域网ip.可是为了实现能够ping通外网.比如 ping baidu.com 还是不行的. 当运行ping baidu.com这个命令时,提示 ping ba ...
- jQuery报错:Uncaught ReferenceError: $ is not defined解决方法
原因及解决办法 1:加载jquery失败,就再次确认jquery的路径是否正确. 2:如果jquery的路径没有问题,那么就可能是浏览器在解释你的js语句时,还没有加载jquery库.所以,你需要将加 ...
- 30天自制OS(linux环境)-day1
30天自制OS(linux环境)--第一天 我是在CentOS的环境上面实现的,使用ubuntu的环境也是类似的 第一步:因为要对二进制文件进行编辑,所以安装二进制编辑器hexedit(当然其他的也可 ...
- Spring boot JPA读取数据库方法
方法1: 1 StringBuffer sb = new StringBuffer(300); 2 sb.append("SELECT v.id, v.container_number, v ...
- sql操作数据库(3)-->外键约束、数据库表之间的关系、三大范式、多表查询、事务
外键约束 在新表中添加外键约束语法: constraint 外键约束名称 foreign key(外键的字段名称) references 主表表名(主键字段名) 在已有表中添加外键约束:alter t ...
- 鸿蒙HarmonyOS应用开发落地实践,Harmony Go 技术沙龙落地北京
12月26日,华为消费者BG软件部开源中心与51CTO Harmony OS技术社区携手,共同主办了主题为"Harmony OS 应用开发落地实践"的 Harmony Go 技术沙 ...
- FTP服务器的搭建和使用(centos7)
1.显示如下图则表示已安装vsftp软件 如过没有则可以通过yum源进行安装 yum install -y vsftpd 操作:service vsftpd start|stop|restart 2. ...