Kafka相关内容总结(存储和性能)
Kafka消息的存储
Kafka的设计基于一种非常简单的指导思想:不是要在内存中保存尽可能多的数据,在需要时将这些数据刷新(flush)到文件系统,而是要做完全相反的事情。所有数据都要立即写入文件系统中持久化的日志中,但不进行刷新数据的任何调用。实际中这样做意味着,数据被传输到OS内核的页面缓存中了,OS随后会将这些数据刷新到磁盘。
大家普遍为“磁盘很慢”,因而人们都对持久化(persistent structure)结构能够提供说得过去的性能抱有怀疑态度。实际上,同人们的期望值相比,磁盘可以说是既很慢又很快,这取决决于磁盘的使用方式。设计的很好的磁盘结构可以和网络一样快。在一个由6个7200rpm的SATA硬盘组成的RAID-5磁盘阵列上,线性写入(linear write)的速度大约是600MB/秒,但随机写入却只有100k/秒,其中的差距接近6000倍。
Kafka并没有在内存中创建缓冲区,然后再向磁盘write的方法,而是直接使用了PageCache。
OS在文件系统的读写上已经做了太多的优化,PageCache就是其中最重要的一种方法.
- 直接使用PageCache有如下几个好处:
- 减少内存开销: Java对象的内存开销(overhead)非常大,往往是对象中存储的数据所占内存的两倍以上。
- 避免GC问题:Java中的内存垃圾回收会随着堆内数据不断增长而变得越来越不明确,回收所花费的代价也会越来越大。
- 简单可靠:OS会调用所有的空闲内存作为PageCache,并在其上做了大量的优化:预读,后写,flush管理等,这些都不用应用层操心,而是由OS自动完成。
由于这些因素,使用文件系统并依赖于PageCache页面缓存要优于自己在内存中维护一个缓存或者什么其他别的结构。
读写空中接力
当写操作发生时,它只是将数据写入Page Cache中,并将该页置上dirty标志。
当读操作发生时,它会首先在Page Cache中查找内容,如果有就直接返回了,没有的话就会从磁盘读取文件再写回Page Cache。
可见,只要生产者与消费者的速度相差不大,消费者会直接读取之前生产者写入Page Cache的数据,大家在内存里完成接力,根本没有磁盘访问。而比起在内存中维护一份消息数据的传统做法,这既不会重复浪费一倍的内存,Page Cache又不需要GC(可以放心使用大把内存了),而且即使Kafka重启了,Page Cache还依然在。
相关内核参数
不能及时flush的话,OS crash(不是应用crash) 可能引起数据丢失;
内核线程pdflush负责将有dirty标记的页面,发送给IO调度层。内核会为每个磁盘起一条pdflush线程,每5秒(/proc/sys/vm/dirty_writeback_centisecs)唤醒一次,根据下面三个参数来决定行为:
/proc/sys/vm/dirty_expire_centiseconds
:如果page dirty的时间超过了30秒(单位是10ms),就会被刷到磁盘,所以crash时最多丢30秒左右的数据。/proc/sys/vm/dirty_background_ratio
:如果dirty page的总大小已经超过了10%的可用内存(cat /proc/meminfo里 MemFree+ Cached - Mapped),则会在后台启动pdflush 线程写盘,但不影响当前的write(2)操作。增减这个值是最主要的flush策略里调优手段。/proc/sys/vm/dirty_ratio
:如果wrte(2)的速度太快,比pdflush还快,dirty page 迅速涨到 10%的总内存(cat /proc/meminfo里的MemTotal),则此时所有应用的写操作都会被block,各自在自己的时间片里去执行flush,因为操作系统认为现在已经来不及写盘了,如果crash会丢太多数据,要让大家都冷静点。这个代价有点大,要尽量避免。在Redis2.8以前,Rewrite AOF就经常导致这个大面积阻塞,现在已经改为Redis每32Mb先主动flush()一下了。
原理分析结论
- Kafka使用文件系统来交换消息,性能是否比使用内存来交换消息的系统要低很多?
- 在Apache Kafka里,消息的读写都发生在内存中(Pagecache),真正写盘的就是那条pdflush内核线程,根本不在Kafka的主流程中,读操作大多数会命中Pagecache,同时由于预读机制存在,所以性能非常好,从原理上有保证的。
- 每个分区一个文件,那么多个分区会有多个文件同时读写,是否会极大的降低性能?
- 首先,由于Kafka读写流程是发生在PageCache中,后台的flush不在主流程中触发,所以正常情况下理论上是没有影响的,除非PageCache占用内存过大,或是释放导致读写消耗Kafka进程的CPU时间。
- 再次,文件都是顺序读写,OS层面有预读和后写机制,即使一台服务器上有多个Partition文件,经过合并和排序后都能获得很好的性能,不会出现文件多了变成随机读写的情况,但是当达到相当多的数量之后,也会存在一定的影响。
- 当PageCache过大,大量触发磁盘I/O的时候,超过了/proc/sys/vm/dirty_ratio,Flush会占用各个应用自己的CPU时间,会对主流程产生影响,让主流程变慢。
- 使用SSD盘并不能显著地改善 Kafka 的性能,主要有两个原因:
- Kafka写磁盘是异步的,不是同步的。就是说,除了启动、停止之外,Kafka的任何操作都不会去等待磁盘同步(sync)完成;而磁盘同步(syncs)总是在后台完成的。这就是为什么Kafka消息至少复制到三个副本是至关重要的,因为一旦单个副本崩溃,这个副本就会丢失数据无法同步写到磁盘。
- 每一个Kafka Partition被存储为一个串行的WAL(Write Ahead Log)日志文件。因此,除了极少数的数据查询,Kafka中的磁盘读写都是串行的。现代的操作系统已经对串行读写做了大量的优化工作。
- 如何对Kafka Broker上持久化的数据进行加密
- 目前,Kafka不提供任何机制对Broker上持久化的数据进行加密。用户可以自己对写入到Kafka的数据进行加密,即是,生产者(Producers)在写Kafka之前加密数据,消费者(Consumers)能解密收到的消息。这就要求生产者(Producers)把加密协议(protocols)和密钥(keys)分享给消费者(Consumers)。
- 另外一种选择,就是使用软件提供的文件系统级别的加密,例如Cloudera Navigator Encrypt。Cloudera Navigator Encrypt是Cloudera企业版(Cloudera Enterprise)的一部分,在应用程序和文件系统之间提供了一个透明的加密层。
- Kafka是否支持跨数据中心的可用性
- Kafka跨数据中心可用性的推荐解决方案是使用MirrorMaker。在你的每一个数据中心都搭建一个Kafka集群,在Kafka集群之间使用MirrorMaker来完成近实时的数据复制。
- 使用MirrorMaker的架构模式是为每一个”逻辑”的topic在每一个数据中心创建一个topic:例如,在逻辑上你有一个”clicks”的topic,那么你实际上有”DC1.clicks”和“DC2.clicks”两个topic(DC1和DC2指得是你的数据中心)。DC1向DC1.clicks中写数据,DC2向DC2.clicks中写数据。MirrorMaker将复制所有的DC1 topics到DC2,并且复制所有的DC2 topics到DC1。现在每个DC上的应用程序都能够访问写入到两个DC的事件。这个应用程序能够合并信息和处理相应的冲突。
- 另一种更复杂的模式是在每一个DC都搭建本地和聚合Kafka集群。这个模式已经被Linkedin使用,Linkedin Kafka运维团队已经在 这篇Blog 中有详细的描述(参见“Tiers and Aggregation”)。
参考
Kafka相关内容总结(存储和性能)的更多相关文章
- Kafka相关内容总结(概念和原理)
说明 主要内容是在网上的一些文章中整理出来: 加粗的字体是比较重要的内容,部分是自己的经验和理解: 整理的目的主要是为了方便查阅: 为什么需要消息系统 解耦: 在项目启动之初来预测将来项目会碰到什么需 ...
- Kafka相关内容总结(Kafka集群搭建手记)
简介 Kafka is a distributed,partitioned,replicated commit logservice.它提供了类似于JMS的特性,但是在设计实现上完全不同,此外它并不是 ...
- kafka相关文章引用
kafka相关内容说明: Kafka压缩 Kafka端到端审计 kafka数据可靠性深度解读 Kafka发送超过broker限定大小的消息时Client和Broker端各自会有什么异常? Kafka之 ...
- Web 前端性能优化相关内容解析
Web 前端性能优化相关内容,来源于<Google官方网页载入速度检测工具PageSpeed Insights 使用教程>一文中PageSpeed Insights 的相关说明.大家可以对 ...
- Web 前端性能优化相关内容解析[转]
Web 前端性能优化相关内容,来源于<Google官方网页载入速度检测工具PageSpeed Insights 使用教程>一文中PageSpeed Insights 的相关说明.大家可以对 ...
- web页面内容优化管理与性能技巧
来源:GBin1.com 回 想一下,以前我们不得不花费大量时间去优化页面内容(图片.CSS等等),如今用户有更快速的互联网链接,我们似乎能够使用更大的图像或更大的闪 存文件,里面包含的有视频或者图片 ...
- MySQL的日志相关内容
本篇文章介绍一下mysql的备份和日志,由于备份时需要用到日志,所以在讲备份前,如果日志内容篇幅过长,将会把日志和备份分开单独来讲,先简单介绍一下mysql的日志相关内容. MySQL日志 日志是my ...
- kafka相关
一.消息队列优点(解耦.异步.削峰)二.用消息队列都有什么优点和缺点?三.kafka.activemq.rabbitmq.rocketmq都有什么区别四.如何保证消息队列的高可用啊?五.如何保证消息不 ...
- Struts2(四)——页面相关内容
上篇博客总结了数据流转各个方面的内容,这篇重点说一下框架对于界面上知识. 一,说到页面,记得在总体介绍中,说到Struts2比Struts1的一方面优势就是它支持更多的视图技术(Freemarker, ...
随机推荐
- Spring Boot: Yaml配置文件 以及 @ConfigurationProperties属性获取
Yaml配置文件 概述 Spring Boot在支持application.properties配置文件的同时,也支持application.yaml配置文件. 配置文件中的属性,可以通过: 通过@V ...
- iOS学习—— UISearchBar的使用
转载自:http://blog.sina.com.cn/s/blog_7b9d64af0101dfg8.html 最近用到搜索功能.于是,经过不断的研究,终于,有点懂了. 那就来总结一下吧,好记性不如 ...
- java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.paipaixiu/com.example.paipaixiu.MASetSomeThing}: android.view.InflateException: Binary XML file line #19: Attempt to invo
这个报错是因为Android布局的控件 <view android:layout_width="match_parent" android:layout_height=&qu ...
- Hive篇--相关概念和使用二
一.基本概念 Hive分桶: 1.概念 分桶表是对列值取哈希值的方式,将不同数据放到不同文件中存储.对于hive中每一个表.分区都可以进一步进行分桶.(可以对列,也可以对表进行分桶)由列的哈希值除以桶 ...
- JVM基础系列第3讲:到底什么是虚拟机?
我们都知道在 Windows 系统上一个软件包装包是 exe 后缀的,而这个软件包在苹果的 Mac OSX 系统上是无法安装的.类似地,Mac OSX 系统上软件安装包则是 dmg 后缀,同样无法在 ...
- 如何为ASP.NET Core的强类型配置对象添加验证
原文: Adding validation to strongly typed configuration objects in ASP.NET Core 作者: Andrew Lock 译文: La ...
- node 调试相关
#0 node 正确的书写方式 为了防止后面出现混乱的各种书写,先来了解一下如何正确书写 node 的名称. 下面使用来自@bitandbang 推文中的图片展示如何正确书写 node 名称. nod ...
- WebApi系列~对HttpClient的响应流进行解压
回到目录 有时我们的请求头为ContentEncoding添加了gzip进行了压缩,而服务端返回数据时也会对它进行gzip压缩,如果在这种情况下,你直接头响应流会是乱码,而必须先进行压缩,大叔将这块的 ...
- Docker 镜像之存储管理
笔者在<Docker 镜像之进阶篇>中介绍了镜像分层.写时复制以及内容寻址存储(content-addressable storage)等技术特性,为了支持这些特性,docker 设计了一 ...
- -1-5 java 多线程 概念 进程 线程区别联系 java创建线程方式 线程组 线程池概念 线程安全 同步 同步代码块 Lock锁 sleep()和wait()方法的区别 为什么wait(),notify(),notifyAll()等方法都定义在Object类中
本文关键词: java 多线程 概念 进程 线程区别联系 java创建线程方式 线程组 线程池概念 线程安全 同步 同步代码块 Lock锁 sleep()和wait()方法的区别 为什么wait( ...