nodejs 如何做网站后端,网站建设相关话术,泰兴市城乡住房建设局网站,济南刚刚发生的大事文章目录 概述一、顺序磁盘I/O (分区顺序追加)1.1 存储架构设计1.2 性能对比实验1.3 存储优化策略 二、零拷贝技术#xff1a;颠覆传统的数据传输革命2.1 传统模式痛点2.2 Kafka优化方案 三、页缓存机制#xff1a;操作系统的隐藏加速器3.1 实现原理3.2 优势对比 四、日志索引… 文章目录 概述一、顺序磁盘I/O (分区顺序追加)1.1 存储架构设计1.2 性能对比实验1.3 存储优化策略 二、零拷贝技术颠覆传统的数据传输革命2.1 传统模式痛点2.2 Kafka优化方案 三、页缓存机制操作系统的隐藏加速器3.1 实现原理3.2 优势对比 四、日志索引设计海量数据的快速检索4.1 存储结构4.2 查询流程 五、批量处理吞吐量的倍增器5.1 生产者配置5.2 消费者配置 六、压缩算法空间与时间的权衡艺术6.1 压缩效率对比6.2 压缩过程 七、Reactor网络模型高并发的基石7.1 模型演进7.2 核心参数 小结 概述
在消息中间件领域Apache Kafka以卓越的吞吐性能著称。虽然RocketMQ在某些场景下展现出更高的吞吐能力但其架构设计仍深受Kafka启发。接下来我们将从存储设计、网络优化、内存管理等维度深入剖析Kafka实现百万级TPS的七大关键技术揭示其高性能背后的设计哲学。 #mermaid-svg-wQIPrq6XH7hsCwzN {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-wQIPrq6XH7hsCwzN .error-icon{fill:#552222;}#mermaid-svg-wQIPrq6XH7hsCwzN .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-wQIPrq6XH7hsCwzN .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-wQIPrq6XH7hsCwzN .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-wQIPrq6XH7hsCwzN .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-wQIPrq6XH7hsCwzN .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-wQIPrq6XH7hsCwzN .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-wQIPrq6XH7hsCwzN .marker{fill:#333333;stroke:#333333;}#mermaid-svg-wQIPrq6XH7hsCwzN .marker.cross{stroke:#333333;}#mermaid-svg-wQIPrq6XH7hsCwzN svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-wQIPrq6XH7hsCwzN .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-wQIPrq6XH7hsCwzN .cluster-label text{fill:#333;}#mermaid-svg-wQIPrq6XH7hsCwzN .cluster-label span{color:#333;}#mermaid-svg-wQIPrq6XH7hsCwzN .label text,#mermaid-svg-wQIPrq6XH7hsCwzN span{fill:#333;color:#333;}#mermaid-svg-wQIPrq6XH7hsCwzN .node rect,#mermaid-svg-wQIPrq6XH7hsCwzN .node circle,#mermaid-svg-wQIPrq6XH7hsCwzN .node ellipse,#mermaid-svg-wQIPrq6XH7hsCwzN .node polygon,#mermaid-svg-wQIPrq6XH7hsCwzN .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-wQIPrq6XH7hsCwzN .node .label{text-align:center;}#mermaid-svg-wQIPrq6XH7hsCwzN .node.clickable{cursor:pointer;}#mermaid-svg-wQIPrq6XH7hsCwzN .arrowheadPath{fill:#333333;}#mermaid-svg-wQIPrq6XH7hsCwzN .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-wQIPrq6XH7hsCwzN .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-wQIPrq6XH7hsCwzN .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-wQIPrq6XH7hsCwzN .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-wQIPrq6XH7hsCwzN .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-wQIPrq6XH7hsCwzN .cluster text{fill:#333;}#mermaid-svg-wQIPrq6XH7hsCwzN .cluster span{color:#333;}#mermaid-svg-wQIPrq6XH7hsCwzN div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-wQIPrq6XH7hsCwzN :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 计算层 存储层 网络层 批量压缩 批量发送 批量解压 顺序写入磁盘 页缓存加速 日志分段存储 稀疏索引跳表 Reactor网络模型 零拷贝传输 零拷贝传输 生产者优化 消费者批量拉取 一、顺序磁盘I/O (分区顺序追加)
1.1 存储架构设计
Kafka采用「分区顺序追加」的写入模式每个分区对应物理磁盘上的独立日志文件 。
生产者消息按分区严格顺序追加到文件尾部避免传统数据库的随机写入模式。 1.2 性能对比实验
根据ACM Queue的研究数据
顺序读磁盘53.2 MB/s随机读内存36.7 MB/s随机读磁盘0.5 KB/s
结论顺序磁盘操作性能比随机内存访问提升45%比随机磁盘访问高出5个数量级。
1.3 存储优化策略
数据如果一直落盘不删除也不行所以Kafka也提供了两种可配置的数据删除策略一种是基于时间另一种就是基于分区文件的大小以此来保障磁盘的数据存储容量。
策略类型配置参数作用时间策略log.retention.hours过期数据自动删除容量策略log.segment.bytes控制单个Segment大小 二、零拷贝技术颠覆传统的数据传输革命
2.1 传统模式痛点
传统文件传输需经历四次拷贝
DMA拷贝到内核缓存CPU拷贝到用户缓存CPU拷贝到Socket缓存DMA拷贝到网卡 2.2 Kafka优化方案
使用Linux的sendfile系统调用实现零拷贝
sendfile(int out_fd, int in_fd, off_t *offset, size_t count);in_fd消息文件描述符offset消费者偏移量count读取字节数
Java NIO通过FileChannel.transferTo()封装此能力实现数据从页缓存直通网卡。 三、页缓存机制操作系统的隐藏加速器
如果只是消息到磁盘的顺序读写还不足以成为高性能的典型所以Kafka还利用了操作系统的页缓存技术利用内存来提升I/O效率。
页缓存通过内存映射文件memory mapped file实现文件到物理内存的直接映射。完成映射之后对物理内存的操作会被同步到磁盘上操作系统在适当的时候。相比用户态的内存页缓存有如下两个优势。
避免用户态对象的内存额外占用例如使用Java堆时Java对象的内存消耗比较大通常是所存储数据的两倍甚至更多。避免用户态的内存垃圾回收用户态的内存垃圾回收会导致运行复杂和缓慢。
因此利用基于操作系统的页缓存Kafka的数据都在内存操作性能又进一步提升。
3.1 实现原理
通过mmap将磁盘文件映射到进程地址空间形成虚拟内存与物理内存的映射关系。当访问虚拟内存地址时
命中页缓存直接读取物理内存未命中页缓存触发缺页中断加载数据
3.2 优势对比
维度用户态缓存页缓存内存占用数据量2倍1:1映射GC影响频繁STW无影响数据同步需手动flush内核自动管理 四、日志索引设计海量数据的快速检索
之前说了Kafka的数据存储是按照分区存储的但是写入文件的最小单位是段segment即一个分区有多个段那么如何提升数据存储和读取性能呢Kafka采取了跳表加索引查询的模式
4.1 存储结构
partition-0/
├── 00000000000000000000.index
├── 00000000000000000000.log
├── 00000000000000000000.timeindex日志文件存储实际消息Segment分段存储索引文件稀疏索引记录offset与物理位置的映射
4.2 查询流程
使用跳表定位目标Segment二分法查询.index文件获取物理偏移从.log文件指定位置顺序扫描 消费者拉取消息的时候首先从日志的segment里的跳表结构查询到消息的偏移量例如上图中查询到的消息偏移量是3再在索引文件里按照消息偏移量查询它在日志文件里对应的日志偏移量例如图中消息偏移量为3在.index文件里对应的日志偏移量是1360接下来直接访问位置1360获取消息message3。通过跳表加索引的结构不仅数据查询的效率提升了数据查询的并行度也提升了 五、批量处理吞吐量的倍增器
数据的批量读取和写入主要是为了解决频繁的网络I/O带来的性能消耗问题例如以极端情况来看假设有10000条消息一次网络请求读写10000条与每次读写1条且用10000次完成相比显然是前一种方式更具性能优势其实这也是前面讲到的粘连分区的一个优势它可以将每次分区的容量填充率变得更高减少消息的网络I/O传输从而实现更低的网络时延。同样在“零拷贝”里面的批量获取容量也是类似的道理。
5.1 生产者配置
batch.size16384 // 批次大小(16KB)
linger.ms5 // 等待时间当满足size或time任一条件即触发发送。
5.2 消费者配置
fetch.min.bytes1
fetch.max.wait.ms500通过「预读取拉取窗口」机制减少网络交互次数。 六、压缩算法空间与时间的权衡艺术
网络I/O传输中最大的损耗由每次传输的消息大小来确定对于需要在广域网上的数据中心之间发送消息的数据流水线尤其如此。进行数据压缩虽然会消耗少量的CPU资源但是对Kafka而言网络I/O资源的占用和优化同样也需要考虑。
如果只是对单个消息进行压缩压缩率就会很低所以Kafka采用了批量压缩即将多个消息一起压缩而不是压缩单个消息。Kafka允许使用递归的消息集合批量的消息可以通过压缩格式传输并且在日志中也可以保持压缩格式直到被消费者解压缩。Kafka支持多种压缩协议包括Gzip和Snappy压缩协议。
6.1 压缩效率对比
算法压缩率CPU消耗适用场景Gzip高高带宽敏感Snappy中低CPU敏感LZ4中高极低实时系统
6.2 压缩过程
[消息1][消息2]...[消息N] → 压缩 → [压缩块]七、Reactor网络模型高并发的基石
Kafka在客户端和服务器端之间通信实现的Reactor网络模型是一种事件驱动模型。
选择器selector也可以称为多路复用器它是Java NIO的核心组件用于检测NIO通道的状态是否可读或可写。接收器acceptor用于监听网络连接端口和请求。OP_WRITENIO的可写状态调用Writer_handler处理。OP_READNIO的可读状态调用Read_handler处理。OP_CONNECTNIO的可连接状态由客户端主动连接触发调用接收器处理。
对于一些小容量的业务场景这种单线程的模式基本够用但是对于高负载、高并发的应用场景这种单线程的模式并不适合主要有以下几个原因
并发性问题一个NIO线程同时处理数十万甚至百万级的链路性能是无法支撑的。吞吐量问题如果超时发生重试会加重服务器端的处理负载从而导致大量处理积压。可靠性问题如果单个线程出现故障整个系统将无法使用会造成单点故障。 7.1 模型演进
传统BIO模型1连接1线程 → 线程数爆炸 单Reactor单线程无法应对高并发 Kafka多Reactor多线程
Acceptor Threads(N) ↓
Processor Threads(M)↓
Handler Thread Pool(P)7.2 核心参数
num.network.threads3 // 网络线程数
num.io.threads8 // IO处理线程因此要实现一个高并发的处理服务需要对以上架构进行优化例如采取多线程处理模式同时将接收线程的逻辑尽量简化相当于将接收线程作为一个接入层。Kafka的Reactor网络模型就是依据这些因素进行优化的 Kafka采取了多线程处理请求机制如图中处理线程池所示并且依据网卡的个数在Kafka源码里面采用EndPoint表示启动相应的接收监听线程图中的接收器从整体上来看实现了多线程接收监听器以及多线程处理器保障了在消息请求接入层的处理性能并且解决了高可用问题 小结 #mermaid-svg-6xQzcdoNqs6D8j47 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-6xQzcdoNqs6D8j47 .error-icon{fill:#552222;}#mermaid-svg-6xQzcdoNqs6D8j47 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-6xQzcdoNqs6D8j47 .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-6xQzcdoNqs6D8j47 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-6xQzcdoNqs6D8j47 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-6xQzcdoNqs6D8j47 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-6xQzcdoNqs6D8j47 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-6xQzcdoNqs6D8j47 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-6xQzcdoNqs6D8j47 .marker.cross{stroke:#333333;}#mermaid-svg-6xQzcdoNqs6D8j47 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-6xQzcdoNqs6D8j47 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-6xQzcdoNqs6D8j47 .cluster-label text{fill:#333;}#mermaid-svg-6xQzcdoNqs6D8j47 .cluster-label span{color:#333;}#mermaid-svg-6xQzcdoNqs6D8j47 .label text,#mermaid-svg-6xQzcdoNqs6D8j47 span{fill:#333;color:#333;}#mermaid-svg-6xQzcdoNqs6D8j47 .node rect,#mermaid-svg-6xQzcdoNqs6D8j47 .node circle,#mermaid-svg-6xQzcdoNqs6D8j47 .node ellipse,#mermaid-svg-6xQzcdoNqs6D8j47 .node polygon,#mermaid-svg-6xQzcdoNqs6D8j47 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-6xQzcdoNqs6D8j47 .node .label{text-align:center;}#mermaid-svg-6xQzcdoNqs6D8j47 .node.clickable{cursor:pointer;}#mermaid-svg-6xQzcdoNqs6D8j47 .arrowheadPath{fill:#333333;}#mermaid-svg-6xQzcdoNqs6D8j47 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-6xQzcdoNqs6D8j47 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-6xQzcdoNqs6D8j47 .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-6xQzcdoNqs6D8j47 .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-6xQzcdoNqs6D8j47 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-6xQzcdoNqs6D8j47 .cluster text{fill:#333;}#mermaid-svg-6xQzcdoNqs6D8j47 .cluster span{color:#333;}#mermaid-svg-6xQzcdoNqs6D8j47 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-6xQzcdoNqs6D8j47 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 生产者批量发送 页缓存 零拷贝传输 消费者批量拉取 跳表快速定位 索引精准查询 Reactor并发处理 Kafka的高吞吐设计体现了多个层级的优化协同
存储层顺序I/O页缓存突破磁盘瓶颈网络层零拷贝批量压缩降低传输损耗计算层Reactor模型多线程提升并发能力架构层分区Segment实现水平扩展