mysql zookeeper 切换_zookeeper在mysql主库选举切换中的应用
為了保證可用性,傳統(tǒng)的關系型數據庫(mysql)通常采用一主多備的方式,當主宕機后,切換到備機。
有多種方式可以做到主備自動失效檢測切換,比如傳統(tǒng)的HA軟件heartbeat,keepalived等等,采取虛擬IP的方式對客戶端透明;
這里主備自動切換方案沒有采取VIP的方式,而是用zookeeper對數據庫集群進行管理,可以做到主備失效檢測切換,主庫的選舉,
比如考慮到mysql對多核利用率不高而一個節(jié)點部署多個mysql實例,如果采用VIP的方式是不可行的。
基本做法是,每個mysql實例上部署一個agent節(jié)點,agent負責對該mysql實例定時進行ping操作,agent在zookeeper上注冊臨時節(jié)點,
如果agent或者該agent代理的mysql宕掉,注冊在zookeeper上的節(jié)點就會發(fā)生變化,利用zookeeper watch功能實現mysq實例失效后的主庫的選舉操作,
讀節(jié)點也通過watch master節(jié)點的功能實現指向新的master。
如上圖所示,zookeeper上的master節(jié)點存儲當前主節(jié)點名稱;
servers下面保存在線的節(jié)點,命名規(guī)則一般為ip:port_序列號;
nodeid為當前的序列號,每當節(jié)點獲取一個序列號時,該節(jié)點值自就增,以便于分配給下一個節(jié)點。
過程如下:
a、初始化階段,創(chuàng)建servers,master,nodeid節(jié)點
b、每個client創(chuàng)建servers子節(jié)點,zoo_create("/servers/xxx",EPHEMERAL)
c、zoo_get_child(/servers,NULL)
d、若當前client的序列號id是當前最小的節(jié)點,則當前節(jié)點是master,設置master節(jié)點退出
e、否則,zoo_exsists(lastid before id,watcher)//當前節(jié)點watch比當前節(jié)點id次小的那個節(jié)點的狀態(tài)
如果id不存在,那么退出
否則等待watch觸發(fā),重新選舉master
相關偽代碼參考示例如下:
try {
ProposoWatcher wc = new ProposoWatcher();
final ZooKeeper zk = new ZooKeeper("10.1.1.24:2181", 60000, wc);
wc.setZk(zk);
if (zk.exists("/master", false) == null) {
zk.create("/master", null, Ids.OPEN_ACL_UNSAFE,
CreateMode.PERSISTENT);
}
zk.create("/servers/" + nodeName, new byte[0], Ids.OPEN_ACL_UNSAFE,
CreateMode.EPHEMERAL);
List list = zk.getChildren("/servers", false);
String[] nodes = list.toArray(new String[list.size()]);
Arrays.sort(nodes);
if (nodeName.equals(nodes[0])) {//初次
System.out.println("this is master" + nodes[0]);
zk.setData("/master", nodeName.getBytes(), -1);
} else {
// 監(jiān)控比自己次小的Node
String lower = "";
for (int i = 0; i < nodes.length; i++) {
if (nodeName.equals(nodes[i])) {
lower = nodes[i - 1];
break;
}
}
zk.exists("/servers/" + lower, true);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//watcher
public static class ProposoWatcher implements Watcher {
private ZooKeeper zk;
public ZooKeeper getZk() {
return zk;
}
public void setZk(ZooKeeper zk) {
this.zk = zk;
}
@Override
public void process(WatchedEvent event) {
// TODO Auto-generated method stub
switch (event.getType()) {
case None: {
// connectionEvent(event);
break;
}
case NodeDeleted: {
// servers.remove(event.getPath());
System.out.println("node? removed**" + event.getPath());
String delName = event.getPath().substring(
event.getPath().lastIndexOf("/"));
// final ZooKeeper zk1 = zk;
List children = new ArrayList();
try {
children = zk.getChildren("/servers", false);
} catch (KeeperException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String[] nodes = children.toArray(new String[children.size()]);
Arrays.sort(nodes);
for (int i = 0; i < nodes.length; i++) {
if (nodes[i].compareTo(delName) > 0) {
// TODO:curr Node become master
System.out.println("this is master" + nodes[i]);
try {
zk.setData("/master", nodes[i].getBytes(), -1);
} catch (KeeperException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
}
}
break;
}
}
}
}
總結
以上是生活随笔為你收集整理的mysql zookeeper 切换_zookeeper在mysql主库选举切换中的应用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: abb变频器电机过热保护怎么复位_变频器
- 下一篇: java获取小数位数_Java获取小数位