漫游Kafka设计篇之数据持久化
Kafka大量依赖文件系统去存储和缓存消息。对于硬盘有个传统的观念是硬盘总是很慢,这使很多人怀疑基于文件系统的架构能否提供优异的性能。实际上硬盘的快慢完全取决于使用它的方式。设计良好的硬盘架构可以和内存一样快。
在6块7200转的SATA RAID-5磁盘阵列的线性写速度差不多是600MB/s,但是随即写的速度却是100k/s,差了差不多6000倍。现代的操作系统都对次做了大量的优化,使用了 read-ahead 和 write-behind的技巧,读取的时候成块的预读取数据,写的时候将各种微小琐碎的逻辑写入组织合并成一次较大的物理写入。对此的深入讨论可以查看这里,它们发现线性的访问磁盘,很多时候比随机的内存访问快得多。
为了提高性能,现代操作系统往往使用内存作为磁盘的缓存,现代操作系统乐于把所有空闲内存用作磁盘缓存,虽然这可能在缓存回收和重新分配时牺牲一些性能。所有的磁盘读写操作都会经过这个缓存,这不太可能被绕开除非直接使用I/O。所以虽然每个程序都在自己的线程里只缓存了一份数据,但在操作系统的缓存里还有一份,这等于存了两份数据。
另外再来讨论一下JVM,以下两个事实是众所周知的:
- Java对象占用空间是非常大的,差不多是要存储的数据的两倍甚至更高。
- 随着堆中数据量的增加,垃圾回收回变的越来越困难。
基于以上分析,如果把数据缓存在内存里,因为需要存储两份,不得不使用两倍的内存空间,Kafka基于JVM,又不得不将空间再次加倍,再加上要避免GC带来的性能影响,在一个32G内存的机器上,不得不使用到28-30G的内存空间。并且当系统重启的时候,又必须要将数据刷到内存中( 10GB 内存差不多要用10分钟),就算使用冷刷新(不是一次性刷进内存,而是在使用数据的时候没有就刷到内存)也会导致最初的时候新能非常慢。但是使用文件系统,即使系统重启了,也不需要刷新数据。使用文件系统也简化了维护数据一致性的逻辑。
所以与传统的将数据缓存在内存中然后刷到硬盘的设计不同,Kafka直接将数据写到了文件系统的日志中。
常量时间的操作效率
在大多数的消息系统中,数据持久化的机制往往是为每个cosumer提供一个B树或者其他的随机读写的数据结构。B树当然是很棒的,但是也带了一些代价:比如B树的复杂度是O(log N),O(log N)通常被认为就是常量复杂度了,但对于硬盘操作来说并非如此。磁盘进行一次搜索需要10ms,每个硬盘在同一时间只能进行一次搜索,这样并发处理就成了问题。虽然存储系统使用缓存进行了大量优化,但是对于树结构的性能的观察结果却表明,它的性能往往随着数据的增长而线性下降,数据增长一倍,速度就会降低一倍。
直观的讲,对于主要用于日志处理的消息系统,数据的持久化可以简单的通过将数据追加到文件中实现,读的时候从文件中读就好了。这样做的好处是读和写都是 O(1) 的,并且读操作不会阻塞写操作和其他操作。这样带来的性能优势是很明显的,因为性能和数据的大小没有关系了。
既然可以使用几乎没有容量限制(相对于内存来说)的硬盘空间建立消息系统,就可以在没有性能损失的情况下提供一些一般消息系统不具备的特性。比如,一般的消息系统都是在消息被消费后立即删除,Kafka却可以将消息保存一段时间(比如一星期),这给consumer提供了很好的机动性和灵活性,这点在今后的文章中会有详述。
漫游Kafka设计篇之数据持久化的更多相关文章
- 漫游Kafka设计篇之Producer和Consumer
Kafka Producer 消息发送 producer直接将数据发送到broker的leader(主节点),不需要在多个节点进行分发.为了帮助producer做到这点,所有的Kafka节点都可以及时 ...
- 漫游Kafka设计篇之Producer和Consumer(4)
Kafka Producer 消息发送 producer直接将数据发送到broker的leader(主节点),不需要在多个节点进行分发.为了帮助producer做到这点,所有的Kafka节点都可以及时 ...
- 漫游Kafka设计篇之性能优化
Kafka在提高效率方面做了很大努力.Kafka的一个主要使用场景是处理网站活动日志,吞吐量是非常大的,每个页面都会产生好多次写操作.读方面,假设每个消息只被消费一次,读的量的也是很大的,Kafka也 ...
- 漫游Kafka设计篇之性能优化(7)
Kafka在提高效率方面做了很大努力.Kafka的一个主要使用场景是处理网站活动日志,吞吐量是非常大的,每个页面都会产生好多次写操作.读方面,假设每个消息只被消费一次,读的量的也是很大的,Kafka也 ...
- 漫游Kafka设计篇之主从同步
Kafka允许topic的分区拥有若干副本,这个数量是可以配置的,你可以为每个topci配置副本的数量.Kafka会自动在每个个副本上备份数据,所以当一个节点down掉时数据依然是可用的. Kafka ...
- 漫游Kafka设计篇之消息传输的事务定义
之前讨论了consumer和producer是怎么工作的,现在来讨论一下数据传输方面.数据传输的事务定义通常有以下三种级别: 最多一次: 消息不会被重复发送,最多被传输一次,但也有可能一次不传输. 最 ...
- 漫游Kafka设计篇之消息传输的事务定义(5)
之前讨论了consumer和producer是怎么工作的,现在来讨论一下数据传输方面.数据传输的事务定义通常有以下三种级别: 最多一次: 消息不会被重复发送,最多被传输一次,但也有可能一次不传输. 最 ...
- 漫游Kafka入门篇之简单介绍
介绍 Kafka是一个分布式的.可分区的.可复制的消息系统.它提供了普通消息系统的功能,但具有自己独特的设计.这个独特的设计是什么样的呢? 首先让我们看几个基本的消息系统术语: Kafka将消息以 ...
- 漫游Kafka入门篇之简单介绍(1)
介绍 Kafka是一个分布式的.可分区的.可复制的消息系统.它提供了普通消息系统的功能,但具有自己独特的设计.这个独特的设计是什么样的呢? 首先让我们看几个基本的消息系统术语: Kafka将消息以 ...
随机推荐
- 还原TexturePacker plist 文件以及图片的方法 (切开各小图片)
原地址:http://blog.csdn.net/linuxchen/article/details/16865645 Python 脚本:(来自网络) unpack_plist.py 命令行: py ...
- Smarty模板学习
1.基本语法 所有的smarty模板标签都被加上了定界符.默认情况下是 { 和},但它们是可被改变的. 在smarty里,所有定界符以外的内容都是静态输出的,或者称之为不可改变.当smarty遇到了模 ...
- JAVA 异常对于性能的影响
陶炳哲 - MAY 12, 2015 在对OneAPM的客户做技术支持时,我们常常会看到很多客户根本没意识到的异常.在消除了这些异常之后,代码运行速度与以前相比大幅提升.这让我们产生一种猜测,就是在代 ...
- hdu 4389 X mod f(x) 数位DP
思路: 每次枚举数字和也就是取模的f(x),这样方便计算. 其他就是基本的数位Dp了. 代码如下: #include<iostream> #include<stdio.h> # ...
- FastJson与Gson小测试
最近用到Json来传输数据,找到两个比较简单的工具 Gson 和 FastJson随便测试一下两个工具的效率~ 1 package com.json.fast; import java.util.Ar ...
- iOS开发--成员变量与属性
属性变量 @interface MyClass:NSObject{ MyObjecct *_object; } @property(nonamtic, retain) MyObjecct *objec ...
- Swagger PHP使用指南
先说什么是Swagger, Swagger的使用目的是方便优美的呈现出接口API的各种定义, 生成API文档, 包括参数, 路径之类. 有时后端改了API的参数或者其他设置, 前端直接看这个Swagg ...
- CentOS软件安装目录查找
注:一般的软件的默认安装目录在/usr/local或者/opt里,可以到那里去找找. 指令名称:whereis 功能介绍:在特定目录中查找符合条件的文件.这些文件的烈性应属于原始代码,二进制文件,或是 ...
- Centos下修改启动项和网络配置
1.Centos默认是从图形界面启动,需要较多的资源,为了节省资源可以从命令行启动.修改方法如下: /etc/inittab文件,把 代码: id:5:initdefault:这一行,修改成 代码: ...
- mysql 生成批量存储过程
CREATE PROCEDURE `BatchInsert`(IN init INT, IN loop_time INT)BEGIN DECLARE Var INT; DECLARE ID INT; ...