Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”.

1. Determine whether to connect to Zookeeper

func (electionManager *ElectionManager) isConnected() bool { if electionManager.ZKClientConn == nil { return false } else if electionManager.ZKClientConn.State() ! = zk.StateConnected { return false } return true }Copy the code

When initializing the Zookeeper connection, we need to check whether Zookeeper is connected. In fact, we can check whether the connection is nil to determine whether the connection is connected or not. If we want to check whether the connection is faulty, we better use the State() method of the connection. It indicates that the connection is successful. If it is other, it indicates that the connection is abnormal. The values of connection exception and success are listed below.

StateUnknown           State = -1
StateDisconnected      State = 0
StateConnecting        State = 1
StateAuthFailed        State = 4
StateConnectedReadOnly State = 5
StateSaslAuthenticated State = 6
StateExpired           State = -112
​
StateConnected  = State(100)
StateHasSession = State(101)
Copy the code

You can see that zk.stateconnected is 100, so maybe you can put zk.stateconnected ected blocks into 100, and I don’t know if that’s a good idea, but you can try ~ StateUnknown or -1, which means the state is unknown, StateDisconnected means 0 is disconnected, but I won’t go into details.

Second, the logic of elections

func (electionManager *ElectionManager) Run() { err := electionManager.electMaster() if err ! = nil { fmt.Println(err) } electionManager.watchMaster() }Copy the code

If this looks familiar, this is what opens up the coroutine run in the main function — elections.

It’s very simple, just vote for the master, and then listen on the master node.

3. Electoral logic

func (electionManager *ElectionManager) electMaster() error { err := electionManager.initConnection() if err ! = nil { return err } isExist, _, err := electionManager.ZKClientConn.Exists(electionManager.ZKConfig.RootPath) if err ! = nil { return err } if ! isExist { path, err := electionManager.ZKClientConn.Create(electionManager.ZKConfig.RootPath, nil, 0, zk.WorldACL(zk.PermAll)) if err ! = nil { return err } if electionManager.ZKConfig.RootPath ! Path = {return errors. The New (" create "+ electionManager. ZKConfig. RootPath +"!" =" + path) } } masterPath := electionManager.ZKConfig.RootPath + electionManager.ZKConfig.MasterPath path, err := electionManager.ZKClientConn.Create(masterPath, nil, zk.FlagEphemeral, Zk.worldacl (zk.permall)) if err == nil {if path == masterPath {FMT.Println(" Select master successfully ") electionManager.isMaster <- True} else {return errors.New(" created "+ masterPath + "! =" + path)}} else {// failed to create a master FMT.Println(" failed to select a master! ") , err) electionManager.IsMaster <- false } return nil }Copy the code

To start the election, you must connect to Zookeeper. InitConnection () is written to connect to ZK and returns a value to determine if there is a problem with the connection.

If zK does not have a root directory, create a root directory. Generally, the root directory data is not set, flags is set to 0, and permissions are not controlled to create persistent nodes.

So let me introduce you to the Create() speaker

Create() takes four parameters, the first is the path to Create, the second is the data content in the node, the third is the node type parameter, flag=0 indicates that this is a persistent node, and the fourth parameter is the permission. Have the following permissions.

PermRead = 1 << iota
PermWrite
PermCreate
PermDelete
PermAdmin
PermAll = 0x1f
Copy the code

Zk.worldacl (zK.permall) indicates that this object has no permission restrictions

FlagEphemeral then concatenates the master address to Create the master node. The third parameter in Create() uses zk.flagephemeral to Create the temporary node because it needs to Create a temporary node. If the master node is successfully created, the master node is successfully elected.

Write true to the isMaster of the connection on success or false on failure.

4. Listen on the Master node

func (electionManager *ElectionManager) watchMaster() error { for { children, state, childCh, err := electionManager.ZKClientConn.ChildrenW(electionManager.ZKConfig.RootPath + electionManager.ZKConfig.MasterPath) if err ! = nil {FMT.Println(" Listen failed!" , err)} FMT.Println(" listen to children ", children, state) select {case childEvent := < -childch: If childevent. Type == zk.eventNodeDeleted {fmt.println (" Received deletion event of ZNode ", childEvent) fmt.println (" start electing new master...") ) err = electionManager.electMaster() if err ! = nil {FMT.Println(" Failed to elect new master ", err)}}}}}Copy the code

You need to listen on the child nodes under the zooKeeper root node. If the connection is disconnected or the corresponding child ZNode is deleted, a re-election is triggered. Therefore, you need to listen on all the child nodes in the directory.

ChildrenW() returns the listening event, and if the listening for the child node is deleted, that is, zK.EventNodeDeleted, electMaster() is called again for election.

See this baby, must be true love, if you like the blogger, remember to like, follow, share three lines