本文讲述基于zookeeper选主与故障切换的方法。我们的例子使用的是python。

使用的库是kazoo,安装方式

pip install kazoo 

应用场景:

  • 多个实例部署,但不是“去中心化”的部署方式;
  • 有且只有一个节点作为master,履行master的职责,在例子中是注册调度器;
  • 其他实例作为slave,不提供调度功能,但是在master节点挂掉之后,可以重新进行选主调度。

1、注册调度器

我们只给出伪代码,简单的打印调度器注册结果。

# -*- coding:utf-8 -*-

# 调度器注册和关闭
# 模拟主节点的职责
class MyScheduler(object): # 注册调度器
def init_scheduler(self):
print '########## 开启调度器成功 ############' # 关闭调度器
def stop_scheduler(self):
print '########## 关闭调度器成功 ############'

2、选主与故障切换代码

1)使用add_listener注册监听器,监听zookeeper会话超时,Session Expired,否则在会话超时的场景中会出现锁不一致的问题,可以参看这篇文章

  • 会话超时之后,我们要重新建立Session,在我们的例子里,会循环直到Session重新建立。
  • 重新注册Watcher,因为Watcher会随着Session失效而失效。在我们的例子里,通过执行get_children重新注册了Watcher。

2)向zookeeper注册自己,使用参数makepath=True级联创建节点;使用参数ephemeral=True, sequence=True参数,也就是创建临时有序节点:

  • 当实例挂掉,session断开,注册的节点会自行消失
  • 有序节点,会节点后添加一个有序编号

3)注册Watcher,观察/dmonitor/master的子节点,当发生以下事件时:

  • Created:新增子节点
  • Deleted:删除子节点
  • Changed:子节点数据变化
  • Child:子节点的下一级节点

进行重新选主。

# -*- coding:utf-8 -*-

import socket
import traceback
from kazoo.client import KazooClient
from kazoo.client import KazooState
from MyScheduler import MyScheduler class HAMaster(object): def __init__(self):
self.path = '/dmonitor/master'
self.scheduler = MyScheduler()
self.zk = KazooClient('10.93.21.21:2181,10.93.18.34:2181,10.93.18.35:2181', timeout=10)
self.zk.start()
self.zk.add_listener(self.my_listener)
self.is_leader = False def create_instance(self):
instance = self.path + '/' + socket.gethostbyname(socket.gethostname()) + '-'
self.zk.create(path=instance, value="", ephemeral=True, sequence=True, makepath=True) # 选主逻辑: master节点下, 所有ephemeral+sequence类型的节点中, 编号最大的获得领导权.
def choose_master(self):
print "########## 选主开始 ############"
instance_list = self.zk.get_children(path=self.path, watch=self.my_watcher)
instance = max(instance_list).split('-')[0]
# 本实例获得领导权
if instance == socket.gethostbyname(socket.gethostname()):
if not self.is_leader:
self.scheduler.init_scheduler()
self.is_leader = True
print "######### 我被选为master, 我以前不是master, 注册调度 ##########"
else:
print "######### 我被选为master, 我以前是master, 不再注册调度 ##########"
# 本实例没有获得领导权
else:
if self.is_leader:
self.scheduler.stop_scheduler()
self.is_leader = False
print "######### 我被选为slave, 我以前不是slave, 关闭调度 ##########"
else:
print "######### 我被选为slave, 我以前是slave, 不再关闭调度 ##########"
print "########## 选主完成 ############" def my_listener(self, state):
if state == KazooState.LOST:
print "########## 会话超时:KazooState.LOST ############"
while True:
try:
self.create_instance()
self.zk.get_children(path=self.path, watch=self.my_watcher)
print "########## 会话超时:重建会话完成! ############"
break
except Exception, _:
traceback.print_exc()
elif state == KazooState.SUSPENDED:
print "########## 会话超时:KazooState.SUSPENDED ############"
elif state == KazooState.CONNECTED:
print "########## 会话超时:KazooState.CONNECTED ############"
else:
print "########## 会话超时:非法状态 ############" def my_watcher(self, event):
if event.state == "CONNECTED" and event.type == "CREATED" or event.type == "DELETED" or event.type == "CHANGED" or event.type == "CHILD":
print "########## 监听到子节点变化事件 ############"
self.choose_master()
else:
print "########## 监听到未识别的事件 ############"

3、测试一下

测试代码如下

# -*- coding:utf-8 -*-
import time
from HAMaster import HAMaster ha = HAMaster()
# 向zk注册自己
ha.create_instance()
# 进行选主
ha.choose_master() while 1:
time.sleep(10)

运行这个脚本,模拟如下几个场景:

1)初始选主

顺序在两台机器上启动测试脚本。

client10

[data_monitor@bigdata-arch-client10 zookeeper]$ python run.py 

client11

[data_monitor@bigdata-arch-client11 zookeeper]$ python run.py 

client10输出

[data_monitor@bigdata-arch-client10 zookeeper]$ python run.py
########## 选主开始 ############
########## 开启调度器成功 ############
######### 我被选为master, 我以前不是master, 注册调度 ##########
########## 选主完成 ############
########## 监听到子节点变化事件 ############
########## 选主开始 ############
######### 我被选为master, 我以前是master, 不再注册调度 ##########
########## 选主完成 ############

client11输出

[data_monitor@bigdata-arch-client11 zookeeper]$ python run.py
########## 选主开始 ############
######### 我被选为slave, 我以前是slave, 不再关闭调度 ##########
########## 选主完成 ############

可以看到,client10倍选为主节点并注册调度器,client11作为slave节点。

2)主实例挂掉

我们把client10上的实例kill掉。

client10上不再输出

client11上总体输出如下

[data_monitor@bigdata-arch-client11 zookeeper]$ python run.py
########## 选主开始 ############
######### 我被选为slave, 我以前是slave, 不再关闭调度 ##########
########## 选主完成 ############
########## 监听到子节点变化事件 ############
########## 选主开始 ############
########## 开启调度器成功 ############
######### 我被选为master, 我以前不是master, 注册调度 ##########
########## 选主完成 ############

可以看到监听到节点的变化,并进行了重新选主,client11被选为主节点(只剩他了)并注册了调度器。

tips:观察到节点变化的实效性是通过timeout=10参数控制的,也就是超过10s session不能维持就会认为实例挂了,zookeeper会删除节点。

kazoo python zookeeper 选主的更多相关文章

  1. zookeeper curator选主(Leader)

    在分布式系统设计中,选主是一个常见的场景.选主是一个这样的过程,通过选主,主节点被选择出来控制其他节点或者是分配任务. 选主算法要满足的几个特征: 1)各个节点均衡的获得成为主节点的权利,一旦主节点被 ...

  2. 聊聊Zookeeper应用场景、架构设计、选主机制

    Zookeeper作为一个分布式协调系统提供了一项基本服务:分布式锁服务,分布式锁是分布式协调技术实现的核心内容.像配置管理.任务分发.组服务.分布式消息队列.分布式通知/协调等,这些应用实际上都是基 ...

  3. Zookeeper笔记之使用zk实现集群选主

    一.需求 在主从结构的集群中,我们假设硬件机器是很脆弱的,随时可能会宕机,当master挂掉之后需要从slave中选出一个节点作为新的master,使用zookeeper可以很简单的实现集群选主功能. ...

  4. 简述 zookeeper 基于 Zab 协议实现选主及事务提交

    Zab 协议:zookeeper 基于 Paxos 协议的改进协议 zookeeper atomic broadcast 原子广播协议. zookeeper 基于 Zab 协议实现选主及事务提交. 一 ...

  5. 使用Kazoo操作ZooKeeper服务治理

    单机服务的可靠性及可扩展性有限,某台服务宕机可能会影响整个系统的正常使用:分布式服务能够有效地解决这一问题,但同时分布式服务也会带来一些新的问题,如:服务发现(新增或者删除了服务如何确保能让客户端知道 ...

  6. kafka分区选主机制

    Kafka Partition Leader选主机制 https://blog.csdn.net/qq_27384769/article/details/80115392 kafka leader选举 ...

  7. Etcd 使用场景:通过分布式锁思路实现自动选主

    分布式锁?选主? 分布式锁可以保证当有多台实例同时竞争一把锁时,只有一个人会成功,其他的都是失败.诸如共享资源修改.幂等.频控等场景都可以通过分布式锁来实现. 还有一种场景,也可以通过分布式锁来实现, ...

  8. python开发_tkinter_窗口控件_自己制作的Python IDEL_博主推荐(二)

    在上一篇blog:python开发_tkinter_窗口控件_自己制作的Python IDEL_博主推荐 中介绍了python中的tkinter的一些东西,你可能对tkinter有一定的了解了.这篇b ...

  9. ES选主策略

    ES版本5.6.3 1.整个流程的开始,实在node启动后触发的,Node.java中start()方法,通过调用ZenDiscovery.java中的doStart()方法,之后会调用startIn ...

随机推荐

  1. JavaScript中你所不知道的Object(二)--Function篇

    上一篇(JavaScript中你所不知道的Object(一))说到,Object对象有大量的内部属性,而其中多数和外部属性的操作有关.最后留了个悬念,就是Boolean.Date.Number.Str ...

  2. 阿里云Prismplayer-Web播放器的使用

    Prismplayer是一套在线视频播放技术方案,同时支持Flash和Html5两种播放技术,可对播放器进行功能配置和皮肤定制.其在线使用文档地址为:https://help.aliyun.com/d ...

  3. 201521123083《Java程序设计》第8周学习总结

    1. 本周学习总结 这周因为一些事情耽搁了,几乎没什么打java代码,这几天尽量补过来 2. 书面作业 1.List中指定元素的删除 1.1 实验总结 不贴大段代码了,简要总结一下.切割成数组,主要用 ...

  4. 团队作业4——第一次项目冲刺(Alpha版本)2017.4.24

    在下午3-4节Linux课结束后,我们teamworkers全体队员留在禹州楼304进行约20分钟的短暂会议,会议讨论关于昨天任务的总结并分配了今天的新任务,大家畅所欲言,情绪高昂,各自阐述了自己不一 ...

  5. Java-反射机制学习

    反射机制是Java的一个重要性,它使得Java语言具有了动态特性.比如说,可以在代码中动态地获取某个类的信息,生成它的实例.获取其成员变量.调用它的方法.下面通过几个示例来演示反射机制的作用与用法. ...

  6. 201521123081《java程序设计》 第7周学习总结

    1. 本周学习总结 以你喜欢的方式(思维导图或其他)归纳总结集合相关内容. 参考资料:XMind 2. 书面作业 Q1. ArrayList代码分析 1.1 解释ArrayList的 contains ...

  7. 201521123001《Java程序设计》第4周学习总结

    1. 本周学习总结 1.1 尝试使用思维导图总结有关继承的知识点. 1.2 使用常规方法总结其他上课内容. 答:1.被继承的类称为父类,继承父类的类称为子类 2.继承时子类将获得父类的属性与方法,并具 ...

  8. 让你的python程序同时兼容python2和python3

    python邮件列表里有人发表言论说「python3在10内都无法普及」.在我看来这样的观点有些过于悲观,python3和python2虽然不兼容,但他们之间差别并没很多人想像的那么大.你只需要对自己 ...

  9. 201521123040《Java程序设计》第12周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多流与文件相关内容. 2. 书面作业 将Student对象(属性:int id, String name,int age,doubl ...

  10. 201521123028 《Java程序设计》第14周学习总结

    1. 本周学习总结 2. 书面作业 1. MySQL数据库基本操作 建立数据库,将自己的姓名.学号作为一条记录插入.(截图,需出现自己的学号.姓名) 在自己建立的数据库上执行常见SQL语句(截图) 2 ...