Original text: Using Zookeeper to realize distributed lock and service registration center
For the definition and principle of Zookeeper, there are already many excellent articles on the Internet that give a detailed introduction to it, so this article does not Let’s discuss this aspect again.
This article mainly introduces some basic preparations and the use of zookeeper.net.
The source code of this article github address: https://github.com/Mike-Zrw/ZookeeperHelper
zookeeper download address: https://archive.apache.org/dist/zookeeper /
ZooInspector download address: https://issues.apache.org/jira/secure/attachment/12436620/ZooInspector.zip
Zookeeper download And installation
The latest version is 3.5.3. The version used in this article is 3.4.10
Freely download a version of the compressed package and unzip it to a certain folder. The startup script of the zookeeper service is in the file under the bin directory: zkServer.cmd
Before the service is started, you need to make basic settings for the configuration file:
Set the conf directory zoo_sample.cfg renamed to zoo.cf
Modify the log file path inside, the content of the file after I am modified is as follows
# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just
# example sakes .
dataDir=data
dataLogDir=data\log
# the port at which the clients will connect
clientPort=2181
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
#
# Be sure to read the maintenance section of the
# administrator guide before turning on autopurge.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to “0” to disable auto purge feature
#autopurge.purgeInterval=1
- tickTime: The time interval for maintaining heartbeats between Zookeepers
- initLimit: The maximum number of heartbeats that can be tolerated during the initial connection between the follower server (F) and the leader server (L) in the cluster (tickTime Quantity), here is 2000*10, if more than 10 heartbeats are still not synchronized, the leader will be re-elected
- syncLimit: the request and response between the follower server (F) and the leader server (L) in the cluster The maximum number of heartbeats (the number of tickTimes) that can be tolerated between. Timeout follwer will be discarded
- dataDir: The directory where Zookeeper saves data, the directory cannot contain Chinese characters
- dataLogDir: The directory where Zookeeper saves log files
- clientPort: Zookeeper Server port
After the configuration is complete, you can double-click zkServer.cmd to start the zookeeper service
ZooInspector installation
ZooInspector is a monitoring tool for zookeeper, you can view zookeeper Data information
After the download is complete, unzip it directly and run zookeeper-dev-ZooInspector.jar. If the default port has not been modified, just click to connect it.
p>
ZooKeeper.Net
Use Nuget to install the ZooKeeper.Net development kit into the project
The following code will establish a zookeeper connection and create a temporary directory named parent
public static void TestConnect()
{
Console.WriteLine("Establish connection");
//The service address is: localhost:2181, the timeout connection is 30 seconds
using (ZooKeeper Instance = new ZooKeeperNet.ZooKeeper("localhost:2181", new TimeSpan(0, 0, 30), new Watcher("new")))
{
Console.WriteLine("Check if there is a parent directory");
var sdata = Instance.Exists("/parent", new Watcher("exists"));
Console.WriteLine(sdata==null?"No":"Yes");
if (sdata==null)
{
Console.WriteLine("Start to create parent directory");
//data: The data associated with the directory is: this is the parentnode data
//acl: Directory access control
//CreateMode: Ephemeral: The directory is a temporary directory, and the directory will be automatically cleared when disconnected. Permanent directory: Persistent Self-incremented directory: ***Sequential
Instance.Create("/parent", "this is the parentnode data".GetBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.Ephemeral);
Console.WriteLine("Create parent directory complete");
Console.WriteLine("Check if there is a parent directory");
sdata = Instance.Exists("/parent", new Watcher("exists2"));
Console.WriteLine(sdata == null? "No": "Yes");
if (sdata != null)
{
Console.WriteLine("Delete parent directory");
Instance.Delete("/parent", 0);
}
}
}
}
The results are as follows
It should be noted that executing this code may report an error indicating connection loss. The reason for the error is that the step of establishing a connection is an asynchronous operation. You should wait for the zookeeper connection to succeed before executing The code below. So this code is just a simple demonstration. The correct usage is attached to nuget
The definition of watch for zookeeper is as follows:
Monitoring is a simple mechanism , So that the client receives notifications about changes in the ZooKeeper collection. The client can set Watches when reading a specific znode. Watches will send notifications of any znode (client registry) changes to registered clients.
Znode changes are changes in the data related to znode or changes in the sub-items of znode. Only trigger watches once. If the client wants to notify again, it must be done through another read operation. When the connection session expires, the client will disconnect from the server and related watches will be deleted.
Each node of Zookeeper is called znode. There are four types of znode: persistent node, temporary node, persistent sequential node, temporary sequential node
here Simply put the following nodes: for example, if I need to create a node named /app, then zookeeper will create a node named /app0000000001, if someone else wants to create one For the sequence node named /app, the name of the newly created node will become /app0000000002
That is to say, the name of the sequence node is specified after it is generated The name plus the ten-digit serial number, the serial number will not be repeated, even if two operations are created at the same time. We can use this feature to implement distributed locks:
The pseudo code of distributed locks is as follows:
public void lock(){
var parentpath=/ lock_
var path = CreateEphemeralSequentialNode(parentpath)
while(true){
var children = get all the child nodes of the parent node
if(path is the smallest among children){
success Acquire the lock
return;
}else{
Monitor and wait for the previous node to be deleted
wait();
}
}
}
< p>The specific code can be viewed on github