一.kafka
Apache Kafka
是一个开源
消息
系统,由
Scala
写成
Kafka
是一个分布式消息队列:生产者、消费者的功能。它提供了
类似于
JMS
的特性,
但是在设计实现上完全不同,此外它并不是
JMS
规范的实现
。
l
无论是kafka
集群,还是producer
和consumer
都依赖于
zookeeper
集群保存一些meta
信息,来保证系统可用性
kafka
具有高的吞吐量内部采用消息的批量处理
消息处理的效率很高。
kafka
的组件介绍
Topic
:消息根据Topic
进行归类
Producer
:发送消息者
Consumer
:消息接受者
broker
:每个kafka
实例(server)
Zookeeper
:依赖集群保存meta
信息。
Topics
组件介绍
Topic
:一类消息,每个topic
将被分成多个partition(
区)
,在集群的配置文件中配置。
partition
:在存储层面是逻辑append log
文件,包含多个segment
文件。
Segement
:消息存储的真实文件,会不断生成新的。
offset
:每条消息在文件中的位置(偏移量)。offset
为一个long
型数字,它是唯一标记一条消息。
partition
1、
在存储层面是逻辑append log
文件,每个partition
有多个segment
组成。
2、
任何发布到此partition
的消息都会被直接追加到log
文件的尾部。
3、
每个partition
在内存中对应一个index
列表,记录每个segment
中的第一条消息偏移。这样查找消息的时候,先在index
列表中定位消息位置,再读取文件,速度块。
发布者发到某个
topic
的消息会被
均匀的分布
到多个
part
上,
broker
收到发布消息往对应
part
的最后一个
segment
上添加该消息。
partition
分布
1、
partitions
分区到不同的server
上,一个partition
保存在一个server
上,避免一个server
上的文件过大,同时可以容纳更多的consumer
消费,
有效提升并发消费的能力。
2、
这个server(
如果保存的是partition
的leader)
负责partition
的读写。可以配置备份。
3、
每个partition
都有一个server
为"leader"
,负责读写,其余的相对备份机为follower
,follower
同步leader
数据,负责leader
死了之后的接管。n
个leader
均衡的分散在每个server
上。
4、
partition
的leader
和follower
之间监控通过zookeeper
完成。
segment
1、
每个segment
中存储多条消息,消息id
由其逻辑位置决定,即从消息id
可直接定位到消息的存储位置,避免id
到位置的额外映射。
2、
当某个segment
上的消息条数达到配置值或消息发布时间超过阈值时,segment
上的消息会被flush
到磁盘,只有flush
到磁盘上的消息订阅者才能订阅到
3、
segment
达到一定的大小(可以通过配置文件设定,
默认1G
)后将不会再往该segment
写数据,broker
会创建新的segment
。
offset
offset
是每条消息的偏移量。
segment
日志文件中保存了一系列"log entries"(
日志条目),
每个log entry
格式为"4
个字节的数字N
表示消息的长度" + "N
个字节的消息内容";
每个日志文件都有一个offset
来唯一的标记一条消息,offset
的值为8
个字节的数字,
表示此消息在此partition
中所处的起始位置.
每个partition
在物理存储层面,
有多个log file
组成(
称为segment).
segment file
的命名为"
最小offset".log.
例如"00000000000.log";
其中"
最小offset"
表示此segment
中起始消息的offset.
配置文件
consumer端
partion buffer
中,消息的条数达到阈值,将触发flush
到磁盘
log.flush.interval.messages=10000
#
消息buffer
的时间,达到阈值,将触发flush
到磁盘
log.flush.interval.ms=3000
#
删除topic
需要server.properties
中设置delete.topic.enable=true
否则只是标记删除
delete.topic.enable=true
producer端
设置发送数据是否需要服务端的反馈,
有三个值0,1,-1
# 0: producer
不会等待broker
发送ack
# 1:
当leader
接收到消息之后发送ack
同步还是异步发送消息,默认“sync
”表同步,"async"
表异步。异步可以提高发送吞吐量,
也意味着消息将会在本地buffer
中,
并适时批量发送,但是也可能导致丢失未发送过去的消息
producer.type=sync
#
在async
模式下,
当message
被缓存的时间超过此值后,
将会批量发送给broker,
默认为5000ms
#
此值和batch.num.messages
协同工作.
queue.buffering.max.ms = 5000
#
在async
模式下,producer
端允许buffer
的最大消息量
#
无论如何,producer
都无法尽快的将消息发送给broker,
从而导致消息在producer
端大量沉积
#
此时,
如果消息的条数达到阀值,
将会导致producer
端阻塞或者消息被抛弃,默认为10000
queue.buffering.max.messages=20000
#
如果是异步,指定每次批量发送数据量,默认为200
batch.num.messages=500
#
当消息在producer
端沉积的条数达到"queue.buffering.max.meesages"
后
#
阻塞一定时间后,
队列仍然没有enqueue(producer
仍然没有发送出任何消息)
#
此时producer
可以继续阻塞或者将消息抛弃,
此timeout
值用于控制"
阻塞"
的时间
# -1:
无阻塞超时限制,
消息不会被抛弃
# 0:
立即清空队列,
消息被抛弃
queue.enqueue.timeout.ms=-1
kafka
如何保证数据的不丢失
生产者如何保证数据的不丢失
kafka
的ack
机制:在kafka
发送数据的时候,每次发送消息都会有一个确认反馈机制,确保消息正常的能够被收到
如果是同步模式:ack
机制能够保证数据的不丢失,如果ack
设置为0
,风险很大,一般不建议设置为0
producer.type=sync
request.required.acks=1
# -1:
当所有的follower
都同步消息成功后发送ack.
request.required.acks=0
如果是异步模式:通过buffer
来进行控制数据的发送,有两个值来进行控制,时间阈值与消息的数量阈值,如果buffer
满了数据还没有发送出去,如果设置的是立即清理模式,风险很大,一定要设置为阻塞模式
结论:producer
有丢数据的可能,但是可以通过配置保证消息的不丢失
producer.type=async 异步模式
request.required.acks=1 需要ack校验机制
queue.buffering.max.ms=5000 队列最大缓存时间大一些5秒
queue.buffering.max.messages=10000 队列最大缓存消息数量大些10000
queue.enqueue.timeout.ms = -1 进入队列超时时间设置为永不超时
batch.num.messages=200 每一批处理消息的数量设置小些200
消费者如何保证数据的不丢失
通过offset commit
来保证数据的不丢失,kafka
自己记录了每次消费的offset
数值,下次继续消费的时候,接着上次的offset
进行消费即可
集群监控工具
ganglia
二.storm
Storm
是一个开源的分布式实时计算系统,可以简单、可靠的处理大量的数据流
storm
的架构
1.
Nimbus
:负责资源分配和任务调度。新版本中的
nimbus
节点可以有多个,做主备
2.
Supervisor
:负责接受
nimbus
分配的任务,启动和停止属于自己管理的
worker
进程。
3.
Worker
:
运行具体处理组件逻辑的进程。
4.
Task
:
worker
中每一个
spout/bolt
的线程称为一个
task.
在
storm0.8
之后,
task
不再与物理线程对应,同一个
spout/bolt
的
task
可能会共享一个物理线程,该线程称为
executor
。最新版本的
Jstorm
已经废除了
task
的概念
N台机器启动storm
服务
nohup bin/storm nimbus >/dev/null 2>&1 &
storm
的编程模型
DataSource:外部数据源
Spout:接受外部数据源的组件,将外部数据源转化成Storm内部的数据,以Tuple为基本的传输单元下发给Bolt
Bolt:接受Spout发送的数据,或上游的bolt的发送的数据。根据业务逻辑进行处理。发送给下一个Bolt或者是存储到某种介质上。介质可以是mongodb或mysql,或者其他。
Tuple:Storm内部中数据传输的基本单元,里面封装了一个List对象,用来保存数据。
StreamGrouping:数据分组策略
7种:shuffleGrouping(Random函数),
Non Grouping(Random函数),
FieldGrouping(Hash取模)、
Local or ShuffleGrouping 本地或随机,优先本地。
其中Local or ShuffleGrouping 是如果分组的时候接收bolt的线程和发送者在一个JVM中默认优先选择一个JVM中的bolt就是local,否则和ShuffleGrouping效果一样。
storm
的并行度
Storm
当中的worker
,executor
,task
之间的相互关系
Worker
:表示一个进程
Executor
:表示由worker
启动的线程
一个worker
只会负责一个topology
任务,不会出现一个worker
负责多个topology
任务的情况。
一个worker
进程当中,可以启动多个线程executor
,也就是说,一个worker
进程可以对应多个executor
线程
task
是实际执行数据处理的最小工作单元(注意,
task
并不是线程)
默认情况下 Storm
会在每个线程上运行一个 task
调整
task
的数量,并不能够实际上提高
storm
的并行度,因为
storm
不管是
spout
还是
bolt
当中的代码都是串行执行的,就算一个
executor
对应多个
task
,这多个
task
也是串行去执行
executor
当中的代码,所以这个调整
task
的个数,实际上并不能提高
storm
的并行度
在实际工作当中,由于spout
与bolt
的数量不能够精准确定,所以需要随时调整spout
与bolt
的数量,所以在storm
当中,我们可以
通过命令来动态的进行调整
storm rebalance mytopo -n 3 -e mySpout=5 -e splitBolt=6 -e countBolt=8
一定要注意:重新调整的时候
=
号两边不要有空格
实时看板案例
支付系统+kafka+storm/Jstorm
集群+redis
集群
redis key value型基于内存的nosql数据库
常用5种数据类型
一:字符串类型string
二:散列类型hash
三:列表类型(list)
内部使用双向链表实现,所以获取越接近两端的元素速度越快,但通过索引访问时会比较慢
四:集合类型(set)
集合类型值具有唯一性,常用操作是向集合添加、删除、判断某个值是否存在,集合内部是使用值为空的散列表实现的。
五:有序集合类型
storm原理
Storm
启动流程分析
1
、客户端运行
storm nimbus
时,会调用
storm
的
python
脚本,该脚本中为每个命令编写一个方法
2
、nibums
启动之后,接受客户端提交任务
3
、
nimbus
接受到任务之后,会将任务进行分配,分配会产生一个
assignment
对象,该对象会保存到
zk
中
4
、supervisor
通过watch
机制,感知到nimbus
在zk
上的任务分配信息,从zk
上拉取任务信息,分辨出属于自己任务。
5
、supervisor
根据自己的任务信息,启动自己的worker
,并分配一个端口。
6
、worker
启动之后,连接zk
,拉取任务
7
、
worker
根据任务类型,分别执行
spout
任务或者
bolt
任务。
消息不丢失机制
通过Ack
机制,很容易做到保证所有数据均被处理,一条都不漏。
另外需要注意的,当
spout
触发
fail
动作时,不会自动重发失败的
tuple
,需要
spout
自己重新获取数据,手动重新再发送一次
ack
机制即, spout
发送的每一条消息,
l
在规定的时间内,spout
收到Acker
的ack
响应,即认为该tuple
被后续bolt
成功处理
l
在规定的时间内,没有收到Acker
的ack
响应tuple
,就触发fail
动作,即认为该tuple
处理失败,
l
或者收到Acker
发送的fail
响应tuple
,也认为失败,触发fail
动作
另外Ack
机制还常用于限流作用:
为了避免spout
发送数据太快,而bolt
处理太慢,常常设置pending
数,当spout
有等于或超过pending
数的tuple
没有收到ack
或fail
响应时,跳过执行nextTuple
,
从而限制spout
发送数据。
通过conf.put(Config.TOPOLOGY_MAX_SPOUT_PENDING, pending);
设置spout pend
数。
这个
timeout
时间可以通过
Config.TOPOLOGY_MESSAGE_TIMEOUT_SECS
来设定。
Timeout
的默认时长为
30
秒
如何使用
Ack
机制
spout
在发送数据的时候带上msgid
设置acker
数至少大于0
;Config.setNumAckers(conf, ackerParal);
在bolt
中完成处理tuple
时,执行OutputCollector.ack(tuple),
当失败处理时,执行OutputCollector.fail(tuple);
推荐使用IBasicBolt
,
因为IBasicBolt
自动封装了OutputCollector.ack(tuple),
处理失败时,抛出FailedException
,则自动执行OutputCollector.fail(tuple)
对于
spout
,有
ISpout
,
IRichSpout
,
BaseRichSpout
对于bolt,有IBolt,IRichBolt,BaseRichBolt,
IBasicBolt,BaseBasicBolt
IBasicBolt
,
BaseBasicBolt
不用每次
execute
完成都写
ack/fail
,因为已经帮你实现好了
storm
的定时器以及与
mysql
的整合使用
日志监控告警系统
getComponentConfiguration()
第一步:导入
jar
包
第二步:创建数据库表
第三步:开发我们的定时任务
第四步:开发我们的规则匹配
bolt
第五步:开发我们的短信与邮件通知
bolt
第六步:开发我们的数据库保存
bolt
第七步:程序入口主函数
路由器数据监控
数据类型梳理