网站开发 jsp加密,网站建设的内容策略,重庆妇科医院哪家好医院公立医院,网络营销的四种方式1、讲一讲Kafka与RocketMQ中存储设计的异同#xff1f; Kafka 中文件的布局是以 Topic/partition #xff0c;每一个分区一个物理文件夹#xff0c;在分区文件级别实现文件顺序写#xff0c;如果一个Kafka集群中拥有成百上千个主题#xff0c;每一个主题拥有上百个分区 Kafka 中文件的布局是以 Topic/partition 每一个分区一个物理文件夹在分区文件级别实现文件顺序写如果一个Kafka集群中拥有成百上千个主题每一个主题拥有上百个分区消息在高并发写入时其IO操作就会显得零散消息分散的落盘策略会导致磁盘IO竞争激烈成为瓶颈其操作相当于随机IO即 Kafka 在消息写入时的IO性能会随着 topic 、分区数量的增长其写入性能会先上升然后下降。
而RocketMQ在消息写入时追求极致的顺序写所有的消息不分主题一律顺序写入 commitlog 文件并不会随着 topic 和 分区数量的增加而影响其顺序性。
在消息发送端消费端共存的场景下随着Topic数的增加Kafka吞吐量会急剧下降而RocketMQ则表现稳定。因此Kafka适合Topic和消费端都比较少的业务场景而RocketMQ更适合多Topic多消费端的业务场景。
2、讲一讲Kafka与RocketMQ中零拷贝技术的运用
什么是零拷贝?
零拷贝(英语: Zero-copy) 技术是指计算机执行操作时CPU不需要先将数据从某处内存复制到另一个特定区域。这种技术通常用于通过网络传输文件时节省CPU周期和内存带宽。
➢零拷贝技术可以减少数据拷贝和共享总线操作的次数消除传输数据在存储器之间不必要的中间拷贝次数从而有效地提高数据传输效率
➢零拷贝技术减少了用户进程地址空间和内核地址空间之间因为上:下文切换而带来的开销
可以看出没有说不需要拷贝只是说减少冗余[不必要]的拷贝。
下面这些组件、框架中均使用了零拷贝技术Kafka、Netty、Rocketmq、Nginx、Apache。
传统数据传送机制
比如读取文件再用socket发送出去实际经过四次copy。
伪码实现如下
buffer File.read()
Socket.send(buffer)
1、第一次将磁盘文件读取到操作系统内核缓冲区
2、第二次将内核缓冲区的数据copy到应用程序的buffer
3、第三步将application应用程序buffer中的数据copy到socket网络发送缓冲区(属于操作系统内核的缓冲区)
4、第四次将socket buffer的数据copy到网卡由网卡进行网络传输。 分析上述的过程虽然引入DMA来接管CPU的中断请求但四次copy是存在“不必要的拷贝”的。实际上并不需要第二个和第三个数据副本。应用程序除了缓存数据并将其传输回套接字缓冲区之外什么都不做。相反数据可以直接从读缓冲区传输到套接字缓冲区。
显然第二次和第三次数据copy 其实在这种场景下没有什么帮助反而带来开销(DMA拷贝速度一般比CPU拷贝速度快一个数量级)这也正是零拷贝出现的背景和意义。
打个比喻200M的数据读取文件再用socket发送出去实际经过四次copy2次cpu拷贝每次100ms 2次DMS拷贝每次10ms
传统网络传输的话合计耗时将有220ms
mmap内存映射RocketMQ使用的
硬盘上文件的位置和应用程序缓冲区(application buffers)进行映射建立一种一一对应关系由于mmap()将文件直接映射到用户空间所以实际文件读取时根据这个映射关系直接将文件从硬盘拷贝到用户空间只进行了一次数据拷贝不再有文件内容从硬盘拷贝到内核空间的一个缓冲区。
mmap内存映射将会经历3次拷贝: 1次cpu copy2次DMA copy
打个比喻200M的数据读取文件再用socket发送出去如果是使用MMAP实际经过三次copy1次cpu拷贝每次100ms 2次DMS拷贝每次10ms合计只需要120ms
从数据拷贝的角度上来看就比传统的网络传输性能提升了近一倍。 RocketMQ源码中的MMAP运用
RocketMQ源码中使用MappedFile这个类类进行MMAP的映射 Kafka中的零拷贝
Kafka两个重要过程都使用了零拷贝技术且都是操作系统层面的狭义零拷贝一是Producer生产的数据存到broker二是 Consumer从broker读取数据。
Producer生产的数据持久化到broker采用mmap文件映射实现顺序的快速写入
Customer从broker读取数据采用sendfile将磁盘文件读到OS内核缓冲区后直接转到socket buffer进行网络发送。
sendfile
linux 2.1支持的sendfile
当调用sendfile()时DMA将磁盘数据复制到kernel buffer然后将内核中的kernel buffer直接拷贝到socket buffer。在硬件支持的情况下甚至数据都并不需要被真正复制到socket关联的缓冲区内。取而代之的是只有记录数据位置和长度的描述符被加入到socket缓冲区中DMA模块将数据直接从内核缓冲区传递给协议引擎从而消除了遗留的最后一次复制。
一旦数据全都拷贝到socket buffersendfile()系统调用将会return、代表数据转化的完成。socket buffer里的数据就能在网络传输了。
sendfile会经历3次拷贝1次CPU copy 2次DMA copy硬件支持的情况下则是2次拷贝0次CPU copy 2次DMA copy。 3、有没有读过RocketMQ源码分享一下
RocketMQ的源码是非常的多我们没有必要把RocketMQ所有的源码都读完所以我们把核心、重点的源码进行解读RocketMQ核心流程如下
启动流程RocketMQ服务端由两部分组成NameServer和BrokerNameServer是服务的注册中心Broker会把自己的地址注册到NameServer生产者和消费者启动的时候会先从NameServer获取Broker的地址再去从Broker发送和接受消息。消息生产流程Producer将消息写入到RocketMQ集群中Broker中具体的Queue。消息消费流程Comsumer从RocketMQ集群中拉取对应的消息并进行消费确认。
NameServer设计亮点
存储基于内存
NameServer存储以下信息
topicQueueTableTopic消息队列路由信息消息发送时根据路由表进行负载均衡
brokerAddrTableBroker基础信息包括brokerName、所属集群名称、主备Broker地址
clusterAddrTableBroker集群信息存储集群中所有Broker名称
brokerLiveTableBroker状态信息NameServer每次收到心跳包是会替换该信息
filterServerTableBroker上的FilterServer列表用于类模式消息过滤。 NameServer的实现基于内存NameServer并不会持久化路由信息持久化的重任是交给Broker来完成。这样设计可以提高NameServer的处理能力。
消息写入流程
RocketMQ使用Netty处理网络broker收到消息写入的请求就会进入SendMessageProcessor类中processRequest方法。 最终进入DefaultMessageStore类中asyncPutMessage方法进行消息的存储 然后消息进入commitlog类中的asyncPutMessage方法进行消息的存储 整个存储设计层次非常清晰大致的层次如下图 业务层也可以称之为网络层就是收到消息之后一般交给SendMessageProcessor来分配交给哪个业务来处理。DefaultMessageStore这个是存储层最核心的入口。
存储逻辑层主要负责各种存储的逻辑里面有很多跟存储同名的类。
存储I/O层主要负责存储的具体的消息与I/O处理。
Commitlog写入时使用可重入锁还是自旋锁
RocketMQ在写入消息到CommitLog中时使用了锁机制即同一时刻只有一个线程可以写CommitLog文件。CommitLog 中使用了两种锁一个是自旋锁另一个是重入锁。源码如下 这里注意lock锁的标准用法是try-finally处理防止死锁问题
另外这里锁的类型可以自主配置。
RocketMQ 官方文档优化建议异步刷盘建议使用自旋锁同步刷盘建议使用重入锁调整Broker配置项useReentrantLockWhenPutMessage默认为false 同步刷盘时锁竞争激烈会有较多的线程处于等待阻塞等待锁的状态如果采用自旋锁会浪费很多的CPU时间所以“同步刷盘建议使用重入锁”。
异步刷盘是间隔一定的时间刷一次盘锁竞争不激烈不会存在大量阻塞等待锁的线程偶尔锁等待就自旋等待一下很短的时间不要进行上下文切换了所以采用自旋锁更合适。
Commitlog写入时使用可重入锁还是自旋锁
RocketMQ在写入消息到CommitLog中时使用了锁机制即同一时刻只有一个线程可以写CommitLog文件。CommitLog 中使用了两种锁一个是自旋锁另一个是重入锁。源码如下 这里注意lock锁的标准用法是try-finally处理防止死锁问题
另外这里锁的类型可以自主配置。
RocketMQ 官方文档优化建议异步刷盘建议使用自旋锁同步刷盘建议使用重入锁调整Broker配置项useReentrantLockWhenPutMessage默认为false 同步刷盘时锁竞争激烈会有较多的线程处于等待阻塞等待锁的状态如果采用自旋锁会浪费很多的CPU时间所以“同步刷盘建议使用重入锁”。
异步刷盘是间隔一定的时间刷一次盘锁竞争不激烈不会存在大量阻塞等待锁的线程偶尔锁等待就自旋等待一下很短的时间不要进行上下文切换了所以采用自旋锁更合适。