Zookeeper entry level knowledge notes

Posted by macastor on Tue, 28 Dec 2021 06:12:33 +0100

First meet Zookeeper

Zookeeper is a sub project under the Apache Hadoop project. It is a tree directory service. The zoo keeper is used to manage Hadoop, Hive, Pig and other animals. Zookeeper is a distributed, open source, distributed application coordination service.

The most commonly used functions: configuration management, distributed lock and cluster management.
(personal feeling is similar to that of Nacos)

Installing Zookeeper

ZooKeeper installation configuration - ZooKeeper tutorial ™ (yiibai.com)
Zookeeper cluster setup - Windows - Nuggets (juejin.cn)
zookeeper cluster construction - YSOcean - blog Park (cnblogs.com)

Operate Zookeeper

data model

zookeeper has a hierarchical tree structure


Each node is called ZNode, and each node will save its own data and node information.
A node can have child nodes and a small amount (1MB) of data storage is allowed.
Nodes can be divided into four categories:

  • PERSISTENT node: session disconnection and server restart are still in progress; child nodes can be created, which can be temporary or PERSISTENT; they cannot have the same name.
  • Temporary node (EPHEMERAL) - e: session is lost when the link is broken; cannot create child nodes; cannot have the same name.
  • PERSISTENT_SEQUENTIAL - s: session disconnection and server restart are still in progress; child nodes can be created, which can be temporary or persistent; nodes with the same name will be added with sequence numbers later.
  • Temporary sequential node (EPHEMERAL_SEQUENTIAL) - es: the session link is broken and disappears; child nodes cannot be created; nodes with the same name will be added with sequence numbers (benefits of using distributed locks)

command

Server command

./zkServer.sh start/status/stop/restart
Client commands
./zkCli.sh -server localhost:2181
create -e/-s/-es [node] [child node] [data]
get [node] = [data]
set node data
delete node sub node
deleteall node
ls -s [node]
...

Java API operations

Curator simplifies development
Common commands:
Link, add, delete and modify query, Watch event monitoring, distributed lock
To carry this big man:
https://gitee.com/gaozhihong/Zookpper_HM

pom file required

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>cn.cl</groupId>
    <artifactId>CuratorApi</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.7</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>2.6.0</version>
            <type>jar</type>
            <exclusions>
                <exclusion>
                    <groupId>org.apache.zookeeper</groupId>
                    <artifactId>zookeeper</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.10</version>
            <type>jar</type>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>2.6.0</version>
            <type>jar</type>
        </dependency>
    </dependencies>
</project>

link

package cn.cl;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;

/**
 * Title: get Zookeeper connection object
 * Author: where is the return journey
 * Time: April 16, 2020 - 15:41
 */
public class CuratorConnection {
	public static void main(String[] args) {
		// Create connection object
		CuratorFramework client = CuratorFrameworkFactory
                .builder()
		// IP address port number
                .connectString("39.98.67.88:2181,39.98.67.88:2182,39.98.67.88:2183")
		// Session timeout
		.sessionTimeoutMs(5000)
		// Reconnection mechanism
		// new RetryOneTime(3000): reconnect once every three seconds, only once
		// new RetryNTimes(3, 3000): reconnection every three seconds, 3 times in total
		// new RetryUntilElapsed(10000, 3000): reconnect every three seconds, and stop the reconnect after 10 seconds
		// New exponential backoffretry (1000, 3): reconnect three times, and the interval between reconnections will be longer and longer
		.retryPolicy(new ExponentialBackoffRetry(1000, 3))
		// Namespace
		.namespace("create")
		// Building connection objects
		.build();	
		// open a connection
		client.start();
		System.out.println(client.isStarted());
		// Close connection
		client.close();
	}
}

New node

package cn.cl;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.BackgroundCallback;
import org.apache.curator.framework.api.CuratorEvent;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.data.ACL;
import org.apache.zookeeper.data.Id;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * Title: new node
 * Author: where is the return journey
 * Time: April 16, 2020 - 18:07
 */
public class CuratorCreate {
	CuratorFramework client;

	/**
	 * @Function: get connection
	 * @Author: Gao Zhihong
	 */
	@Before
	public void before() {
		// Create connection object
		client = CuratorFrameworkFactory
		.builder()
		// IP address port number
        	.connectString("39.98.67.88:2181,39.98.67.88:2182,39.98.67.88:2183")
		// Session timeout
		.sessionTimeoutMs(5000)
		// Reconnection mechanism
		// new RetryOneTime(3000): reconnect once every three seconds, only once
		// new RetryNTimes(3, 3000): reconnection every three seconds, 3 times in total
		// new RetryUntilElapsed(10000, 3000): reconnect every three seconds, and stop the reconnect after 10 seconds
		// New exponential backoffretry (1000, 3): reconnect three times, and the interval between reconnections will be longer and longer
		.retryPolicy(new ExponentialBackoffRetry(1000, 3))
		// Namespace
		.namespace("create")
		// Building connection objects
		.build();
		// open a connection
		client.start();
	}

	/**
	 * @Function: add node
	 * @Author: Gao Zhihong
	 */
	@Test
	public void create1() throws Exception {
		String path = client.create()
		// Type of node
		.withMode(CreateMode.PERSISTENT)
		// Permission list of node world:anyone:cdrwa
		.withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE)
		// First parameter: node name
		// The second parameter: node data
		.forPath("/node1", "node1".getBytes());
		System.out.println(path);
	}

	/**
	 * @Function: create node and customize permission list
	 * @Author: Gao Zhihong
	 */
	@Test
	public void create2() throws Exception {
		// Permission list
		List<ACL> acls = new ArrayList<>();
		// Authorization mode and object
		Id id = new Id("ip", "39.98.67.88");
		acls.add(new ACL(ZooDefs.Perms.ALL, id));
		String path = client.create()
		.withMode(CreateMode.PERSISTENT)
		.withACL(acls)
		.forPath("/node2", "node2".getBytes());
		System.out.println(path);
	}

	/**
	 * @Function: create node tree recursively
	 * @Author: Gao Zhihong
	 */
	@Test
	public void create3() throws Exception {
		String path = client.create()
		// Support the creation of recursive nodes
		.creatingParentsIfNeeded()
		.withMode(CreateMode.PERSISTENT)
		.withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE)
		.forPath("/node3/node31", "node31".getBytes());
		System.out.println(path);
	}

	/**
	 * @Function: create node asynchronously
	 * @Author: Gao Zhihong
	 */
	@Test
	public void create4() throws Exception {
		client.create()
		.creatingParentsIfNeeded()
		.withMode(CreateMode.PERSISTENT)
		.withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE)
		.inBackground(new BackgroundCallback() {
		@Override
			public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent) throws Exception {
				// Path of node
				System.out.println(curatorEvent.getPath());
				// Event type
				System.out.println(curatorEvent.getType());
			}
		})
		.forPath("/node4", "node4".getBytes());
		TimeUnit.SECONDS.sleep(1);
	}

	/**
	 * @Function: close connection
	 * @Author: Gao Zhihong
	 */
	@After
	public void after() {
		if (client != null) {
			client.close();
		}
	}
}

Delete node

package cn.cl;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.BackgroundCallback;
import org.apache.curator.framework.api.CuratorEvent;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.concurrent.TimeUnit;

/**
 * Title: delete node
 * Author: where is the return journey
 * Time: April 16, 2020 - 18:07
 */
public class CuratorDelete {
	CuratorFramework client;

	/**
	 * @Function: get connection
	 * @Author: Gao Zhihong
	 */
	@Before
	public void before() {
		// Create connection object
		client = CuratorFrameworkFactory
				.builder()
				// IP address port number
				.connectString("39.98.67.88:2181,39.98.67.88:2182,39.98.67.88:2183")
				// Session timeout
				.sessionTimeoutMs(5000)
				// Reconnection mechanism
				// new RetryOneTime(3000): reconnect once every three seconds, only once
				// new RetryNTimes(3, 3000): reconnection every three seconds, 3 times in total
				// new RetryUntilElapsed(10000, 3000): reconnect every three seconds, and stop the reconnect after 10 seconds
				// New exponential backoffretry (1000, 3): reconnect three times, and the interval between reconnections will be longer and longer
				.retryPolicy(new ExponentialBackoffRetry(1000, 3))
				// Namespace
				.namespace("delete")
				// Building connection objects
				.build();
		// open a connection
		client.start();
	}

	/**
	 * @Function: delete node
	 * @Author: Gao Zhihong
	 */
	@Test
	public void delete1() throws Exception {
		client.delete()
		// First parameter: node path
		.forPath("/node1");
		System.out.println("Deleted!");
	}

	/**
	 * @Function: delete nodes and perform version detection
	 * @Author: Gao Zhihong
	 */
	@Test
	public void delete2() throws Exception {
		client.setData()
		// Version number - 1 identifies the ignored version number
		.withVersion(0)
		.forPath("/node1");
		System.out.println("Deleted");
	}

	/**
	 * @Function: delete nodes containing child nodes
	 * @Author: Gao Zhihong
	 */
	@Test
	public void delete3() throws Exception {
		client.delete()
		// If there are child nodes, they will be deleted together
		.deletingChildrenIfNeeded()
		.withVersion(-1)
		.forPath("/node1");
		System.out.println("Deleted");
	}

	/**
	 * @Function: delete node asynchronously
	 * @Author: Gao Zhihong
	 */
	@Test
	public void delete4() throws Exception {
		client.delete()
		.deletingChildrenIfNeeded()
		.withVersion(0)
		.inBackground(new BackgroundCallback() {
			@Override
			public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent) throws Exception {
				System.out.println(curatorEvent.getPath());
				System.out.println(curatorEvent.getType());
			}
		})
		.forPath("/node1");
		TimeUnit.SECONDS.sleep(1);
		System.out.println("Deleted");
	}

	/**
	 * @Function: close connection
	 * @Author: Gao Zhihong
	 */
	@After
	public void after() {
		if (client != null) {
			client.close();
		}
	}
}

Query node

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.BackgroundCallback;
import org.apache.curator.framework.api.CuratorEvent;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.data.Stat;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.concurrent.TimeUnit;

/**
 * Title: query node
 * Author: where is the return journey
 * Time: April 16, 2020 - 18:07
 */
public class CuratorGet {
	CuratorFramework client;

	/**
	 * @Function: get connection
	 * @Author: Gao Zhihong
	 */
	@Before
	public void before() {
		// Create connection object
		client = CuratorFrameworkFactory
		.builder()
		// IP address port number
		.connectString("39.98.67.88:2181,39.98.67.88:2182,39.98.67.88:2183")
		// Session timeout
		.sessionTimeoutMs(5000)
		// Reconnection mechanism
		// new RetryOneTime(3000): reconnect once every three seconds, only once
		// new RetryNTimes(3, 3000): reconnection every three seconds, 3 times in total
		// new RetryUntilElapsed(10000, 3000): reconnect every three seconds, and stop the reconnect after 10 seconds
		// New exponential backoffretry (1000, 3): reconnect three times, and the interval between reconnections will be longer and longer
		.retryPolicy(new ExponentialBackoffRetry(1000, 3))
		// Namespace
		.namespace("get")
		// Building connection objects
		.build();
		// open a connection
		client.start();
	}

	/**
	 * @Function: query node content
	 * @Author: Gao Zhihong
	 */
	@Test
	public void get1() throws Exception {
		byte[] bytes = client.getData()
		// First parameter: node path
		.forPath("/node1");
		System.out.println(new String(bytes));
	}

	/**
	 * @Function: query node attributes
	 * @Author: Gao Zhihong
	 */
	@Test
	public void get2() throws Exception {
		Stat stat = new Stat();
		client.getData()
		// read attribute
		.storingStatIn(stat)
		.forPath("/node1");
		System.out.println(stat);
	}

	/**
	 * @Function: asynchronous query node
	 * @Author: Gao Zhihong
	 */
	@Test
	public void get3() throws Exception {
		client.getData()
		.inBackground(new BackgroundCallback() {
			@Override
			public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent) throws Exception {
				System.out.println(curatorEvent.getPath());
				System.out.println(curatorEvent.getType());
				System.out.println(new String(curatorEvent.getData()));
			}
		})
		.forPath("/node1");
		TimeUnit.SECONDS.sleep(1);
	}

	/**
	 * @Function: close connection
	 * @Author: Gao Zhihong
	 */
	@After
	public void after() {
		if (client != null) {
			client.close();
		}
	}
}


Query child node

package cn.cl;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.BackgroundCallback;
import org.apache.curator.framework.api.CuratorEvent;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * Title: query child nodes
 * Author: where is the return journey
 * Time: April 16, 2020 - 18:07
 */
public class CuratorGetChildren {
	CuratorFramework client;

	/**
	 * @Function: get connection
	 * @Author: Gao Zhihong
	 */
	@Before
	public void before() {
		// Create connection object
		client = CuratorFrameworkFactory
		.builder()
		// IP address port number
		.connectString("39.98.67.88:2181,39.98.67.88:2182,39.98.67.88:2183")
		// Session timeout
		.sessionTimeoutMs(5000)
		// Reconnection mechanism
		// new RetryOneTime(3000): reconnect once every three seconds, only once
		// new RetryNTimes(3, 3000): reconnection every three seconds, 3 times in total
		// new RetryUntilElapsed(10000, 3000): reconnect every three seconds, and stop the reconnect after 10 seconds
		// New exponential backoffretry (1000, 3): reconnect three times, and the interval between reconnections will be longer and longer
		.retryPolicy(new ExponentialBackoffRetry(1000, 3))
		// Building connection objects
		.build();
		// open a connection
		client.start();
	}

	/**
	 * @Function: query child node content
	 * @Author: Gao Zhihong
	 */
	@Test
	public void getChildren1() throws Exception {
		List<String> childrens = client.getChildren()
		// First parameter: node path
		.forPath("/get");
		childrens.forEach(System.out::println);
	}

	/**
	 * @Function: asynchronously query child nodes
	 * @Author: Gao Zhihong
	 */
	@Test
	public void getChildren2() throws Exception {
		client.getChildren()
		.inBackground(new BackgroundCallback() {
			@Override
			public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent) throws Exception {
				curatorEvent.getChildren().forEach(System.out::println);
			}
		})
		.forPath("/get");
		TimeUnit.SECONDS.sleep(3);
	}

	/**
	 * @Function: close connection
	 * @Author: Gao Zhihong
	 */
	@After
	public void after() {
		if (client != null) {
			client.close();
		}
	}
}

Query whether the node exists

package cn.cl;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.BackgroundCallback;
import org.apache.curator.framework.api.CuratorEvent;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.data.Stat;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.concurrent.TimeUnit;

/**
 * Title: check whether the node exists
 * Author: where is the return journey
 * Time: April 16, 2020 - 18:07
 */
public class CuratorExists {
	CuratorFramework client;

	/**
	 * @Function: get connection
	 * @Author: Gao Zhihong
	 */
	@Before
	public void before() {
		// Create connection object
		client = CuratorFrameworkFactory
		.builder()
		// IP address port number
		.connectString("39.98.67.88:2181,39.98.67.88:2182,39.98.67.88:2183")
		// Session timeout
		.sessionTimeoutMs(5000)
		// Reconnection mechanism
		// new RetryOneTime(3000): reconnect once every three seconds, only once
		// new RetryNTimes(3, 3000): reconnection every three seconds, 3 times in total
		// new RetryUntilElapsed(10000, 3000): reconnect every three seconds, and stop the reconnect after 10 seconds
		// New exponential backoffretry (1000, 3): reconnect three times, and the interval between reconnections will be longer and longer
		.retryPolicy(new ExponentialBackoffRetry(1000, 3))
		// Namespace
		.namespace("get")
		// Building connection objects
		.build();
		// open a connection
		client.start();
	}

	/**
	 * @Function: judge whether a node exists
	 * @Author: Gao Zhihong
	 */
	@Test
	public void exists1() throws Exception {
		Stat stat = client.checkExists()
		// First parameter: node path
		.forPath("/node2");
		System.out.println(stat);
	}


	/**
	 * @Function: determine whether a node exists asynchronously
	 * @Author: Gao Zhihong
	 */
	@Test
	public void exists2() throws Exception {
		client.checkExists()
		.inBackground(new BackgroundCallback() {
			@Override
			public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent) throws Exception {
				System.out.println(curatorEvent.getPath());
				System.out.println(curatorEvent.getType());
				System.out.println(curatorEvent.getStat());
			}
		})
		.forPath("/node1");
		TimeUnit.SECONDS.sleep(3);
	}

	/**
	 * @Function: close connection
	 * @Author: Gao Zhihong
	 */
	@After
	public void after() {
		if (client != null) {
			client.close();
		}
	}
}


Modify node

package cn.cl;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.BackgroundCallback;
import org.apache.curator.framework.api.CuratorEvent;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.data.Stat;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.concurrent.TimeUnit;

/**
 * Title: modifying nodes
 * Author: where is the return journey
 * Time: April 16, 2020 - 18:07
 */
public class CuratorSet {
	CuratorFramework client;

	/**
	 * @Function: get connection
	 * @Author: Gao Zhihong
	 */
	@Before
	public void before() {
		// Create connection object
		client = CuratorFrameworkFactory
		.builder()
		// IP address port number
		.connectString("39.98.67.88:2181,39.98.67.88:2182,39.98.67.88:2183")
		// Session timeout
		.sessionTimeoutMs(5000)
		// Reconnection mechanism
		// new RetryOneTime(3000): reconnect once every three seconds, only once
		// new RetryNTimes(3, 3000): reconnection every three seconds, 3 times in total
		// new RetryUntilElapsed(10000, 3000): reconnect every three seconds, and stop the reconnect after 10 seconds
		// New exponential backoffretry (1000, 3): reconnect three times, and the interval between reconnections will be longer and longer
		.retryPolicy(new ExponentialBackoffRetry(1000, 3))
		// Namespace
		.namespace("set")
		// Building connection objects
		.build();
		// open a connection
		client.start();
	}

	/**
	 * @Function: update nodes
	 * @Author: Gao Zhihong
	 */
	@Test
	public void set1() throws Exception {
		Stat stat = client.setData()
		// First parameter: node path
		// Second parameter: node data
		.forPath("/node1", "hello".getBytes());
		System.out.println(stat);
	}

	/**
	 * @Function: update nodes and perform version detection
	 * @Author: Gao Zhihong
	 */
	@Test
	public void set2() throws Exception {
		Stat stat = client.setData()
		// Version number - 1 identifies the ignored version number
		.withVersion(1)
		.forPath("/node1", "world".getBytes());
		System.out.println(stat);
	}

	/**
	 * @Function: modify nodes asynchronously
	 * @Author: Gao Zhihong
	 */
	@Test
	public void set3() throws Exception {
		client.setData()
		.withVersion(2)
		.inBackground(new BackgroundCallback() {
			@Override
			public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent) throws Exception {
				System.out.println(curatorEvent.getPath());
				System.out.println(curatorEvent.getType());
			}
		})
		.forPath("/node1", "Ha ha ha".getBytes());
		TimeUnit.SECONDS.sleep(1);
	}

	/**
	 * @Function: close connection
	 * @Author: Gao Zhihong
	 */
	@After
	public void after() {
		if (client != null) {
			client.close();
		}
	}
}

event listeners

package cn.cl;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.cache.*;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.concurrent.TimeUnit;

/**
 * Title: event listening mechanism
 * Author: where is the return journey
 * Time: April 16, 2020 - 18:07
 */
public class CuratorWatcher {
	CuratorFramework client;

	/**
	 * @Function: get connection
	 * @Author: Gao Zhihong
	 */
	@Before
	public void before() {
		// Create connection object
		client = CuratorFrameworkFactory
		.builder()
		// IP address port number
		.connectString("39.98.67.88:2181,39.98.67.88:2182,39.98.67.88:2183")
		// Session timeout
		.sessionTimeoutMs(5000)
		// Reconnection mechanism
		// new RetryOneTime(3000): reconnect once every three seconds, only once
		// new RetryNTimes(3, 3000): reconnection every three seconds, 3 times in total
		// new RetryUntilElapsed(10000, 3000): reconnect every three seconds, and stop the reconnect after 10 seconds
		// New exponential backoffretry (1000, 3): reconnect three times, and the interval between reconnections will be longer and longer
		.retryPolicy(new ExponentialBackoffRetry(1000, 3))
		// Building connection objects
		.build();
		// open a connection
		client.start();
	}

	/**
	 * @Function: monitor the data change of a node
	 * @Author: Gao Zhihong
	 */
	@Test
	public void watcher1() throws Exception {
		// Parameter 1: connection object
		// Parameter 2: monitored node path
		final NodeCache nodeCache = new NodeCache(client, "/watcher1");
		// Launch interpreter object
		nodeCache.start();
		nodeCache.getListenable().addListener(new NodeCacheListener() {
			// Method of callback when node changes
			@Override
			public void nodeChanged() throws Exception {
				System.out.println(nodeCache.getCurrentData().getPath());
				System.out.println(new String(nodeCache.getCurrentData().getData()));
				System.out.println(nodeCache.getCurrentData().getStat());
			}
		});
		TimeUnit.SECONDS.sleep(30);
		// Close monitor object
		nodeCache.close();
	}

	/**
	 * @Function: monitor the data change of a child node
	 * @Author: Gao Zhihong
	 */
	@Test
	public void watcher2() throws Exception {
		// Parameter 1: connection object
		// Parameter 2: monitored node path
		// Parameter 3: whether node data can be obtained in the event
		final PathChildrenCache pathChildrenCache = new PathChildrenCache(client, "/watcher1", true);
		// Launch interpreter object
		pathChildrenCache.start();
		pathChildrenCache.getListenable().addListener(new PathChildrenCacheListener() {
			// The method of callback when the child node method changes
			@Override
			public void childEvent(CuratorFramework curatorFramework, PathChildrenCacheEvent pathChildrenCacheEvent) throws Exception {
				// Event type of node
				System.out.println(pathChildrenCacheEvent.getType());
				// Path of node
				System.out.println(pathChildrenCacheEvent.getData().getPath());
				// Node data
				System.out.println(new String(pathChildrenCacheEvent.getData().getData()));
			}
		});
		TimeUnit.SECONDS.sleep(30);
		// Close monitor object
		pathChildrenCache.close();
	}

	/**
	 * @Function: close connection
	 * @Author: Gao Zhihong
	 */
	@After
	public void after() {
		if (client != null) {
			client.close();
		}
	}
}

affair

package cn.cl;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.transaction.CuratorTransactionResult;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.ZooDefs;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.Collection;

/**
 * Title: transaction
 * Author: where is the return journey
 * Time: April 16, 2020 - 18:07
 */
public class CuratorTransaction {
	CuratorFramework client;

	/**
	 * @Function: get connection
	 * @Author: Gao Zhihong
	 */
	@Before
	public void before() {
		// Create connection object
		client = CuratorFrameworkFactory
		.builder()
		// IP address port number
		.connectString("39.98.67.88:2181,39.98.67.88:2182,39.98.67.88:2183")
		// Session timeout
		.sessionTimeoutMs(5000)
		// Reconnection mechanism
		// new RetryOneTime(3000): reconnect once every three seconds, only once
		// new RetryNTimes(3, 3000): reconnection every three seconds, 3 times in total
		// new RetryUntilElapsed(10000, 3000): reconnect every three seconds, and stop the reconnect after 10 seconds
		// New exponential backoffretry (1000, 3): reconnect three times, and the interval between reconnections will be longer and longer
		.retryPolicy(new ExponentialBackoffRetry(1000, 3))
		// Namespace
		.namespace("create")
		// Building connection objects
		.build();
		// open a connection
		client.start();
	}

	/**
	 * @Function: transaction
	 * @Author: Gao Zhihong
	 */
	@Test
	public void transaction1() throws Exception {
		// Open transaction
		Collection<CuratorTransactionResult> collection = client.inTransaction()
		.create()
		.withMode(CreateMode.PERSISTENT)
		.withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE)
		.forPath("/node1", "node1".getBytes())
		.and()
		.create().forPath("/node2", "node2".getBytes())
		.and()
		// Commit transaction
		.commit();
		System.out.println(collection);
	}

	/**
	 * @Function: close connection
	 * @Author: Gao Zhihong
	 */
	@After
	public void after() {
		if (client != null) {
			client.close();
		}
	}
}

Distributed lock

package cn.cl;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.locks.InterProcessLock;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.framework.recipes.locks.InterProcessReadWriteLock;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.concurrent.TimeUnit;

/**
 * Title: distributed lock
 * Author: where is the return journey
 * Time: April 16, 2020 - 18:07
 */
public class CuratorLock {
	CuratorFramework client;

	/**
	 * @Function: get connection
	 * @Author: Gao Zhihong
	 */
	@Before
	public void before() {
		// Create connection object
		client = CuratorFrameworkFactory
		.builder()
		// IP address port number
				.connectString("39.98.67.88:2181,39.98.67.88:2182,39.98.67.88:2183")
		// Session timeout
		.sessionTimeoutMs(5000)
		// Reconnection mechanism
		// new RetryOneTime(3000): reconnect once every three seconds, only once
		// new RetryNTimes(3, 3000): reconnection every three seconds, 3 times in total
		// new RetryUntilElapsed(10000, 3000): reconnect every three seconds, and stop the reconnect after 10 seconds
		// New exponential backoffretry (1000, 3): reconnect three times, and the interval between reconnections will be longer and longer
		.retryPolicy(new ExponentialBackoffRetry(1000, 3))
		// Building connection objects
		.build();
		// open a connection
		client.start();
	}

	/**
	 * @Function: exclusive lock
	 * @Author: Gao Zhihong
	 */
	@Test
	public void lock1() throws Exception {
		// Parameter 1: connection object
		// Parameter 2: node path
		InterProcessLock interProcessLock = new InterProcessMutex(client, "/lock1");
		System.out.println("Waiting to acquire lock object");
		// Acquire lock
		interProcessLock.acquire();
		for (int i = 0; i < 5; i++) {
			TimeUnit.SECONDS.sleep(1);
			System.out.println(i);
		}
		System.out.println("Waiting to release the lock");
		// Release lock
		interProcessLock.release();
	}

	/**
	 * @Function: read / write lock - read lock
	 * @Author: Gao Zhihong
	 */
	@Test
	public void lock2() throws Exception {
		// Read write lock
		InterProcessReadWriteLock readWriteLock = new InterProcessReadWriteLock(client, "/lock1");
		// Get read lock object
		InterProcessMutex interProcessMutex = readWriteLock.readLock();
		System.out.println("Waiting to acquire lock object");
		// Acquire lock
		interProcessMutex.acquire();
		for (int i = 0; i < 10; i++) {
			TimeUnit.SECONDS.sleep(1);
			System.out.println(i);
		}
		System.out.println("Waiting to release the lock");
		// Release lock
		interProcessMutex.release();
	}

	/**
	 * @Function: read / write lock - write lock
	 * @Author: Gao Zhihong
	 */
	@Test
	public void lock3() throws Exception {
		// Read write lock
		InterProcessReadWriteLock readWriteLock = new InterProcessReadWriteLock(client, "/lock1");
		// Get read lock object
		InterProcessMutex interProcessMutex = readWriteLock.writeLock();
		System.out.println("Waiting to acquire lock object");
		// Acquire lock
		interProcessMutex.acquire();
		for (int i = 0; i < 10; i++) {
			TimeUnit.SECONDS.sleep(1);
			System.out.println(i);
		}
		System.out.println("Waiting to release the lock");
		// Release lock
		interProcessMutex.release();
	}

	/**
	 * @Function: close connection
	 * @Author: Gao Zhihong
	 */
	@After
	public void after() {
		if (client != null) {
			client.close();
		}
	}
}

Zookeeper cluster installation

Step 1: configure JAVA environment and verify environment: java -version

Step 2: Download and unzip zookeeper

# cd /usr/local
# wget http://mirror.bit.edu.cn/apache/zookeeper/stable/zookeeper-3.4.12.tar.gz
# tar -zxvf zookeeper-3.4.12.tar.gz
# cd zookeeper-3.4.12

Step 3: Rename zoo_sample.cfg file

# cp conf/zoo_sample.cfg conf/zoo-1.cfg

Step 4: modify the configuration file zoo-1 CFG, some in the original configuration file are modified to the following values, and those without are added

# vim conf/zoo-1.cfg
dataDir=/tmp/zookeeper-1
clientPort=2181
server.1=127.0.0.1:2888:3888
server.2=127.0.0.1:2889:3889
server.3=127.0.0.1:2890:3890

Configuration description

  • tickTime: this time is used as the time interval between Zookeeper servers or between clients and servers to maintain heartbeat, that is, a heartbeat will be sent every tickTime.
  • initLimit: this configuration item is used to configure the maximum number of heartbeat intervals that the Zookeeper receiving client (the client mentioned here is not the client that the user connects to the Zookeeper server, but the Follower server connected to the Leader in the Zookeeper server cluster) can endure when initializing the connection. When the time has exceeded 10 heartbeats The Zookeeper server has not received the return information from the client after the length of (that is, tickTime), which indicates that the client connection failed. The total length of time is 10 * 2000 = 20 seconds
  • syncLimit: this configuration item identifies the length of message sending, request and response time between Leader and Follower. The maximum length of time can not exceed the length of tickTime. The total length of time is 5 * 2000 = 10 seconds
  • dataDir: as the name suggests, it is the directory where Zookeeper saves data. By default, Zookeeper also saves the log files that write data in this directory.
  • clientPort: this port is the port where the client connects to the zookeeper server. Zookeeper will listen to this port and accept the client's access requests.
  • server.A=B: C: D: where a is a number, indicating the server number; B is the ip address of the server; C represents the port where the server exchanges information with the Leader server in the cluster; D means that in case the Leader server in the cluster hangs up, a port is needed to re elect and select a new Leader, and this port is the port used to communicate with each other during the election. In case of pseudo cluster configuration, since B is the same, the communication port numbers of different Zookeeper instances cannot be the same, so they should be assigned different port numbers.

Step 5: identify Server ID
Create three folders / tmp/zookeeper-1, / tmp/zookeeper-2, / tmp/zookeeper-2, create the file myid file in each directory, and write the server id of the current instance, i.e. 1.2 3.

# cd /tmp/zookeeper-1
# vim myid
1
# cd /tmp/zookeeper-2
# vim myid
2
# cd /tmp/zookeeper-3
# vim myid
3

Step 6: start three zookeeper instances

# bin/zkServer.sh start conf/zoo-1.cfg
# bin/zkServer.sh start conf/zoo-2.cfg
# bin/zkServer.sh start conf/zoo-3.cfg

Step7: to detect the cluster status, you can also directly use the command "zkCli.sh -server IP:PORT" to connect to the zookeeper server for detection

How Zookeeper works

Zookeeper introduction read this article is enough_ Technology sharing
Detailed explanation of zookeeper principle - Zhihu (zhihu.com)
What can we do with zookeeper
ZooKeeper interview questions (2020 latest edition)
5 minutes to let you understand the function and principle of ZooKeeper
Detailed explanation of ZooKeeper concept, the most complete arrangement_ salutary influence of education

Topics: Zookeeper Distribution Cloud Native