ZooKeeper数据模型的结构与Linux文件系统很类似,整体上可以看作是一棵树,每个节点称做一个ZNode。每一个ZNode默认能够存储1MB的数据,每个ZNode都可以通过其路径唯一标识。
提供的服务包括:统一命名服务、统一配置管理、统一集群管理、服务器节点动态上下线、软负载均衡等
统一命名服务:
在分布式环境下,经常需要对应用/服务进行统一命名,便于识别。例如:IP不容易记住,而域名容易记住。
统一配置管理:
1)分布式环境下,配置文件同步非常常见。一般要求一个集群中,所有节点的配置信息是一致的,比如Kafka集群。对配置文件修改后,希望能够快速同步到各个节点上。
2)配置管理可交由ZooKeeper实现。可将配置信息写入ZooKeeper上的一个Znode。各个客户端服务器监听这个Znode。一旦 Znode中的数据被修改,ZooKeeper将通知各个客户端服务器。
统一集群管理:
1)分布式环境中,实时掌握每个节点的状态是必要的。可根据节点实时状态做出一些调整。
2)ZooKeeper可以实现实时监控节点状态变化。可将节点信息写入ZooKeeper上的一个ZNode。监听这个ZNode可获取它的实时状态变化。
服务器动态上下线:
客户端能实时洞察到服务器上下线的变化
软负载均衡
在Zookeeper中记录每台服务器的访问数,让访问数最少的服务器去处理最新的客户端请求。
第一次启动选举机制
非第一次启动选举机制
当ZooKeeper 集群中的一台服务器出现以下两种情况之一时,就会开始进入Leader选举:
而当一台机器进入Leader选举流程时,当前集群也可能会处于以下两种状态:
SID:服务器ID。用来唯一标识一台ZooKeeper集群中的机器,每台机器不能重复,和myid一致。
ZXID:事务ID。ZXID是一个事务ID,用来标识一次服务器状态的变更。在某一时刻,集群中的每台机器的ZXID值不一定完全一致,这和ZooKeeper服务器对于客户端“更新请求”的处理逻辑速度有关。
Epoch:每个Leader任期的代号。没有Leader时同一轮投票过程中的逻辑时钟值是相同的。每投完一次票这个数据就会增加
准备 3 台服务器做 Zookeeper 集群
192.168.24.72
192.168.24.73
192.168.24.74
//关闭防火墙
systemctl stop firewalld
systemctl disable firewalld
setenforce 0
在这里插入代码片//安装 JDK
yum install -y java-1.8.0-openjdk java-1.8.0-openjdk-devel
java -version
//下载安装包
官方下载地址:https://archive.apache.org/dist/zookeeper/
cd /opt
wget https://archive.apache.org/dist/zookeeper/zookeeper-3.5.7/apache-zookeeper-3.5.7-bin.tar.gz
在这里插入代码片cd /opt
tar -zxvf apache-zookeeper-3.5.7-bin.tar.gz
mv apache-zookeeper-3.5.7-bin /usr/local/
//修改配置文件
cd /usr/local/zookeeper-3.5.7/conf/
cp zoo_sample.cfg zoo.cfg
vim zoo.cfg
tickTime=2000 #通信心跳时间,Zookeeper服务器与客户端心跳时间,单位毫秒
initLimit=10 #Leader和Follower初始连接时能容忍的最多心跳数(tickTime的数量),这里表示为10*2s
syncLimit=5 #Leader和Follower之间同步通信的超时时间,这里表示如果超过5*2s,Leader认为Follwer死掉,并从服务器列表中删除Follwer
dataDir=/usr/local/zookeeper-3.5.7/data ●修改,指定保存Zookeeper中的数据的目录,目录需要单独创建
dataLogDir=/usr/local/zookeeper-3.5.7/logs ●添加,指定存放日志的目录,目录需要单独创建
clientPort=2181 #客户端连接端口
#添加集群信息
server.1=192.168.24.72:3188:3288
server.2=192.168.24.73:3188:3288
server.3=192.168.24.74:3188:3288
//拷贝配置好的 Zookeeper 配置文件到其他机器上
scp /usr/local/zookeeper-3.5.7/conf/zoo.cfg 192.168.80.11:/usr/local/zookeeper-3.5.7/conf/
scp /usr/local/zookeeper-3.5.7/conf/zoo.cfg 192.168.80.12:/usr/local/zookeeper-3.5.7/conf/
//在每个节点上创建数据目录和日志目录
mkdir /usr/local/zookeeper-3.5.7/data
mkdir /usr/local/zookeeper-3.5.7/logs
//在每个节点的dataDir指定的目录下创建一个 myid 的文件
echo 1 > /usr/local/zookeeper-3.5.7/data/myid
echo 2 > /usr/local/zookeeper-3.5.7/data/myid
echo 3 > /usr/local/zookeeper-3.5.7/data/myid
官方下载地址:http://kafka.apache.org/downloads.html
cd /opt/
tar zxvf kafka_2.13-2.7.1.tgz
mv kafka_2.13-2.7.1 /usr/local/kafka
cd /usr/local/kafka/config/
cp server.properties{,.bak}
#给配置文件进行备份
vim server.properties
broker.id=0 ●21行,broker的全局唯一编号,每个broker不能重复,因此要在其他机器上配置 broker.id=1、broker.id=2
listeners=PLAINTEXT://192.168.80.10:9092 ●31行,指定监听的IP和端口,如果修改每个broker的IP需区分开来,也可保持默认配置不用修改
num.network.threads=3 #42行,broker 处理网络请求的线程数量,一般情况下不需要去修改
num.io.threads=8 #45行,用来处理磁盘IO的线程数量,数值应该大于硬盘数
socket.send.buffer.bytes=102400 #48行,发送套接字的缓冲区大小
socket.receive.buffer.bytes=102400 #51行,接收套接字的缓冲区大小
socket.request.max.bytes=104857600 #54行,请求套接字的缓冲区大小
log.dirs=/usr/local/kafka/logs #60行,kafka运行日志存放的路径,也是数据存放的路径
num.partitions=1 #65行,topic在当前broker上的默认分区个数,会被topic创建时的指定参数覆盖
num.recovery.threads.per.data.dir=1 #69行,用来恢复和清理data下数据的线程数量
log.retention.hours=168 #103行,segment文件(数据文件)保留的最长时间,单位为小时,默认为7天,超时将被删除
log.segment.bytes=1073741824 #110行,一个segment文件最大的大小,默认为 1G,超出将新建一个新的segment文件
zookeeper.connect=192.168.24.75:2181,192.168.24.76:2181,192.168.24.77:2181 ●123行,配置连接Zookeeper集群地址
使用scp命令将配置文件传输到对应服务器上
scp -r kafka/ 192.168.24.76:`pwd`
scp -r kafka/ 192.168.24.77:`pwd`
将里面的id换成不同的和IP地址换成对应的ip地址
zookeeper.connect=192.168.24.75:2181,192.168.24.75:2181,192.168.24.75:2181, #配置连接zookeeper的集群地址
vim /etc/profile
export KAFKA_HOME=/usr/local/kafka
export PATH=$PATH:$KAFKA_HOME/bin
source /etc/profile
vim /etc/init.d/kafka
#!/bin/bash
#chkconfig:2345 22 88
#description:Kafka Service Control Script
KAFKA_HOME='/usr/local/kafka'
case $1 in
start)
echo "---------- Kafka 启动 ------------"
${KAFKA_HOME}/bin/kafka-server-start.sh -daemon ${KAFKA_HOME}/config/server.properties
;;
stop)
echo "---------- Kafka 停止 ------------"
${KAFKA_HOME}/bin/kafka-server-stop.sh
;;
restart)
$0 stop
$0 start
;;
status)
echo "---------- Kafka 状态 ------------"
count=$(ps -ef | grep kafka | egrep -cv "grep|$$")
if [ "$count" -eq 0 ];then
echo "kafka is not running"
else
echo "kafka is running"
fi
;;
*)
echo "Usage: $0 {start|stop|restart|status}"
esac
chmod +x /etc/init.d/kafka
service kafka start
netstat -lntp | grep 9092
在192.168.24.75上启动服务
./kafka-server-start.sh -daemon /usr/local/kafka/config/server.properties
1、创建topic
kafka-topics.sh --create --zookeeper 192.168.24.75:2181,192.168.24.76:2181,192.168.24.77:2181 --replication-factor 2 --partitions 3 --topic test
--zookeeper:定义 zookeeper 集群服务器地址,如果有多个 IP 地址使用逗号分割,一般使用一个 IP 即可
--replication-factor:定义分区副本数,1 代表单副本,建议为 2
--partitions:定义分区数
--topic:定义 topic 名称
2、查看当前服务器中的所有 topic和topic的详情
kafka-topics.sh --list --zookeeper 192.168.24.75:2181,192.168.24.76:2181,192.168.24.77:2181
3、发布消息
kafka-console-producer.sh --broker-list 192.168.24.75:2181,192.168.24.76:2181,192.168.24.77:2181 --topic test
4、消费消息
kafka-console-consumer.sh --bootstrap-server 192.168.24.75:2181,192.168.24.76:2181,192.168.24.77:2181 --topic test --from-beginning
5、按顺序写入数据
可以边写入数据边消费
6、修改分区数
kafka-topics.sh --zookeeper 192.168.24.75:2181,192.168.24.76:2181,192.168.24.77:2181 --alter --topic test --partitions 6
7、删除 topic
kafka-topics.sh --delete --zookeeper 192.168.24.75:2181,192.168.24.76:2181,192.168.24.77:2181 --topic test
Kafka 中消息是以 topic 进行分类的,生产者生产消息,消费者消费消息,都是面向 topic 的。
topic 是逻辑上的概念,而 partition 是物理上的概念,每个 partition 对应于一个 log 文件,该 log 文件中存储的就是 producer 生产的数据。Producer 生产的数据会被不断追加到该 log 文件末端,且每条数据都有自己的 offset。 消费者组中的每个消费者,都会实时记录自己消费到了哪个 offset,以便出错恢复时,从上次的位置继续消费。
由于生产者生产的消息会不断追加到 log 文件末尾,为防止 log 文件过大导致数据定位效率低下,Kafka 采取了分片和索引机制,将每个 partition 分为多个 segment。每个 segment 对应两个文件:“.index” 文件和 “.log” 文件。这些文件位于一个文件夹下,该文件夹的命名规则为:topic名称+分区序号。例如,test 这个 topic 有三个分区, 则其对应的文件夹为 test-0、test-1、test-2。
index 和 log 文件以当前 segment 的第一条消息的 offset 命名。
“.index” 文件存储大量的索引信息,
“.log” 文件存储大量的数据,索引文件中的元数据指向对应数据文件中 message 的物理偏移地址。
LEO:指的是每个副本最大的 offset;
HW:指的是消费者能见到的最大的 offset,所有副本中最小的 LEO。
1)follower 故障
2)leader 故障
对于某些不太重要的数据,对数据的可靠性要求不是很高,能够容忍数据的少量丢失,所以没必要等 ISR 中的 follower 全部接收成功。所以 Kafka 为用户提供了三种可靠性级别,用户根据对可靠性和延迟的要求进行权衡选择。
当 producer 向 leader 发送数据时,可以通过 request.required.acks 参数来设置数据可靠性的级别:
三种机制性能依次递减,数据可靠性依次递增。
注:在 0.11 版本以前的Kafka,对此是无能为力的,只能保证数据不丢失,再在下游消费者对数据做全局去重。在 0.11 及以后版本的 Kafka,引入了一项重大特性:幂等性。所谓的幂等性就是指 Producer 不论向 Server 发送多少次重复数据, Server 端都只会持久化一条。
1、修改配置文件
cd /usr/local/filebeat
- type: log
enabled: true
paths:
- /var/log/httpd/access
tags: ["httpd_acces"]
- type: log
enabled: true
paths:
- /var/log/httpd/error_log
tags: ["httpd_error"]
2、添加输出到 Kafka 的配置
output.kafka:
enable: true
hosts: ["192.168.24.75:9092,192.168.24.76:9092,192.168.24.77:9092"]
topic: "httpd"
3、启动 filebeat
cd /opt/filebeat-6.7.2-linux-x86_64
./filebeat -e -c filebeat.yml
4、部署 ELK,在 Logstash 组件所在节点上新建一个 Logstash 配置文件
cd /etc/logstash/conf.d/
vim kafka.conf
input {
kafka {
bootstrap_servers => "192.168.24.75:9092,192.168.24.76:9092,192.168.24.77:9092" #kafka集群地址
topics => "httpd" #拉取的kafka的指定topic
type => "httpd_kafka" #指定 type 字段
codec => "json" #解析json格式的日志数据
auto_offset_reset => "latest"#拉取最近数据,earliest为从头开始拉取
decorate_events => false #传递给elasticsearch的数据额外增加kafka的属性数据
}
}
output {
if "httpd_access" in [tags] {
elasticsearch {
hosts => ["192.168.24.72:9200","192.168.24.74:9200"]
index => "httpd_access-%{+YYYY.MM.dd}"
}
}
if "httpd_error" in [tags] {
elasticsearch {
hosts => ["192.168.24.72:9200","192.168.24.74:9200"]
index => "httpd_error-%{+YYYY.MM.dd}"
}
}
stdout { codec => rubydebug }
}
5、启动 logstash
logstash -f /etc/logstash/conf.d/filebeat.conf
6、使用浏览器进行访问登录Kibana
浏览器访问 http://192.168.24.73:5601