php+zookeeper 集群管理 – 陈思敏捷


本站和网页 https://www.chenjie.info/1942 的作者无关,不对其内容负责。快照谨为网络故障时之索引,不代表被搜索网站的即时页面。

php+zookeeper 集群管理 – 陈思敏捷
跳至内容
陈思敏捷
陈捷的博客chenjie.info
主要菜单
首页关于博主
我的音乐
蜗牛快跑
留言板
php+zookeeper 集群管理
在 2018/03/242018/03/30 上张贴 由 chenjie发表回复
内容
隐藏
监听机器的退出加入
选举主节点
上一篇提到了php操作zookeeper的一些常用curd操作和需要注意的问题
本篇主要说下具体zookeeper的一种应用场景:集群管理(图片来自网络)
在此我们主要关注两点
监听机器的退出加入
上图中所有机器约定在父节点GroupMembers下创建临时节点,然后监听父节点的子节点。一旦有机器挂掉,该机器与zookeeper的连接断开,其所创建的临时节点被删除,所有其他机器都收到通知某个兄弟节点被删除。新机器加入也是类似,所有机器收到通知,有新增临时节点。
在此特别备注下监听父节点下的子节点只能监听到子节点的新增和删除的事件,子节点本身内容变更父节点并不能捕获,如果需要捕获子节点内容变化的事件,需要对子节点做单独监听
选举主节点
通常集群我们需要一个主节点来对外响应调度分发任务给从节点执行,所以在集群中选举主节点也是异常重要的。选举主节点也有两种主要方式
1 排它式,我们让所有集群所有机器尝试对一个未创建的节点创建临时节点,如果创建成功了则标记该机器为主节点,其他机器继续监听该节点,一旦主节点机器和zookeeper连接断开,其他机器监听到删除事件继续对该节点尝试创建来获得主节点标识,不过在这里当机器数量比较多的时候主节点机器断连会导致其他机器都接收该删除事件会导致惊群,会对服务端造成比较大的性能影响,所以我们推荐第二种方式来解决该问题。
2 共享式,如上图中我们让所有机器在父节点GroupMembers下创建临时顺序节点,机器创建节点拉取GroupMembers所有子节点判断自己编号是不是最小,如果最小则标记为主节点,如果不是最小则监听前一个节点。如果主节点和zookeeper断连则后一个顺序节点(即兄弟节点)可以监听到主节点的删除事件则此时顺利升级为新的主节点。此方式的好处的是每台机器只需要监听前一个兄弟节点,有效避免了惊群问题。下面附上此方案的示例代码,代码修改自网络测试可用。
<?php
class Worker extends Zookeeper{
const CONTAINER = '/chenjie.info';
protected $acl = array(
array(
'perms' => Zookeeper::PERM_ALL,
'scheme' => 'world',
'id' => 'anyone'
);
private $isLeader = false;
private $znode;
public function __construct($host = '', $watcher_cb = null, $recv_timeout = 10000){
parent::__construct($host, $watcher_cb, $recv_timeout);
public function register(){
if (! $this->exists(self::CONTAINER)) {
$this->create(self::CONTAINER, null, $this->acl);
$this->znode = $this->create(self::CONTAINER . '/w-', null, $this->acl, Zookeeper::EPHEMERAL | Zookeeper::SEQUENCE);
$this->znode = str_replace(self::CONTAINER . '/', '', $this->znode);
printf("I'm registerd as %s\n", $this->znode);
$watching = $this->watchPrevious();
if ($watching == $this->znode) {
printf("Nobody here , I'm the leader\n");
$this->setleader(true);
} else {
printf("I'm watching %s\n", $watching);
public function watchPrevious(){
$workers = $this->getChildren(self::CONTAINER);
sort($workers);
$size = sizeof($workers);
for ($i = 0; $i < $size; $i ++) {
if ($this->znode == $workers[$i]) {
if ($i > 0) {
$res = $this->get(self::CONTAINER . '/' . $workers[$i - 1], array(
$this,
'watchNode'
));
return $workers[$i - 1];
return $workers[$i];
throw new Exception(sprintf("Something went very wrong! I can't find myself: %s/%s", self::CONTAINER, $this->znode));
public function watchNode(){
$watching = $this->watchPrevious();
if ($watching == $this->znode) {
printf("I'm the new leader\n");
$this->setLeader(true);
} else {
printf("Now I'm watching %s\n", $watching);
public function isLeader(){
return $this->isLeader;
public function setLeader($flag){
$this->isLeader = $flag;
public function run(){
$this->register();
while (true) {
if ($this->isLeader()) {
$this->doLeaderJob();
} else {
$this->doWorkerJob();
sleep(2);
public function doLeaderJob(){
echo "Leading\n";
public function doWorkerJob(){
echo "Working\n";
$worker = new Worker('localhost:2181');
$worker->run();
执行效果:
为了测试方便对比,我们启动两个客户端,第一个客户端因为刚启动只有一个它自己所以编号最小成为主节点,然后我们断开第一个客户端,观察第二个客户端监听到第一个客户端(前一个节点)断连 然后接任为新的主节点。
张贴在Linux、PHP、开源社区标签:Leader Election、php+zookeeper、zookeeper、主节点选举、共享式、排它式、选举主节点、集群管理
文章导航
&larr; php+zookeeper的curd操作基于Redis实现的延迟队列 &rarr;
发表回复 取消回复您的电子邮箱地址不会被公开。 必填项已用*标注评论 * 显示名称 *
电子邮箱地址 *
网站地址
&#916;
此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据。
Search for:
2022年 12月
1234
567891011
12131415161718
19202122232425
262728293031
&laquo; 10月
标签301tool
2181
apache
cdfs
curl
docker-compose
Elasticsearch
es
firebug
goroutine
heap
ip
javascript
jQuery
jQuery Form Plugin
js
kloxo
map
MongoDB
MySQL
PHP
php301
Prometheus
scp
svn
sync
ThinkPHP
tpm
Vagrant
vps
wamp
weibo
word
wp插件
zookeeper
二级指针
全民K歌
右键
并发
微博
批量删除
插件
网站价值
自动关机
谷歌字体
友情链接
梦幻人生
梦康
Copyright 2022 , 陈思敏捷 ,
苏ICP备18067862号