Docker 下的Zookeeper以及.ne core 的分布式锁
单节点
1.拉取镜像:docker pull zookeeper
2.运行容器
a.我的容器同一放在/root/docker下面,然后创建相应的目录和文件,
mkdir zookeeper
cd zookeeper
mkdir data
mkdir datalog
mkdir conf
cd conf
touch zoo.cfg
其中zoo.cfg(这里是默认的主要延时怪哉文件)如下:
tickTime=
initLimit=
syncLimit=
dataDir=/data
dataLogDir=/datalog
clientPort=
maxClientCnxns=

这里也设置了zookeeper默认的环境变量

b.运行实例,切换到/root/docker/zookeeper下载执行(不知道为什么这里zoo.cfg一定要用相对路径,用绝对路径提示docker-entrypoint.sh: line 15: /conf/zoo.cfg: Is a directory)
docker run --name zookeeper --restart always -d -v$(pwd)/data:/data -v$(pwd)/datalog:/datalog -v $(pwd)/conf/zoo.cfg:/conf/zoo.cfg -p : -p : -p : zookeeperp : -p : -p : zookeeper
# 2181端口号是zookeeper client端口
# 2888端口号是zookeeper服务之间通信的端口
# 3888端口是zookeeper与其他应用程序通信的端口
#用绝对路径 docker run --name zookeeper --restart always -d -v/root/docker/zookeep/data:/data -v/root/docker/zookeep/datalog:/datalog -v /root/docker/zookeep/conf/zoo.cfg:/conf/zoo.cfg -p : -p : -p : zookeeper
#提示/docker-entrypoint.sh: line : /conf/zoo.cfg: Is a directory
docker run --name zookeeper --restart always -d -v/root/docker/zookeep/data:/data -v/root/docker/zookeep/datalog:/datalog -v /root/docker/zookeep/conf/:/conf/ -p : -p : -p : zookeeper #正确的用法是不指定文件
c.zookeeper常规操作,首先执行以下指令进入zookeeper客服端:
docker exec -it zookeeper zkCli.sh -server 192.168.100.5: #如果是集群server用逗号分割 -server 192.168.100.5:,192.168.100.6: create /zk "zkval1" #创建zk节点
create /zk/test1 "testval1" #创建zk/test1节点
create /zk/test2 "testval2" #创建zk/test2节点
#create /test/node "node1" 失败,不支持递归创建,多级时,必须一级一级创建
#create /zk/test2/ null 节点不能以 / 结尾,会直接报错
ls -s /zk #查看zk节点信息
set /zk/test1 "{1111}" #修改节点数据
get /zk/test1 #查看节点数据
delete /zk #删除时,须先清空节点下的内容,才能删除节点
delete /zk/test2

集群搭建
我这里搞了很久,最后还是用官网的配置 创建docker-compose.yml文件如下:
version: '3.1' services:
zoo1:
image: zookeeper
restart: always
hostname: zoo1
ports:
- :
environment:
ZOO_MY_ID:
ZOO_SERVERS: server.=0.0.0.0::; server.=zoo2::; server.=zoo3::; zoo2:
image: zookeeper
restart: always
hostname: zoo2
ports:
- :
environment:
ZOO_MY_ID:
ZOO_SERVERS: server.=zoo1::; server.=0.0.0.0::; server.=zoo3::; zoo3:
image: zookeeper
restart: always
hostname: zoo3
ports:
- :
environment:
ZOO_MY_ID:
ZOO_SERVERS: server.=zoo1::; server.=zoo2::; server.=0.0.0.0::;
最后运行docker-compose up指令,最后验证,
docker exec -it zookeeper_zoo1_1 zkCli.sh -server 192.168.100.5:
create /zk "test"
quit #退出容器1 docker exec -it zookeeper_zoo2_1 zkCli.sh -server 192.168.100.5:
get /zk #在容器2获取值
quit docker exec -it zookeeper_zoo3_1 zkCli.sh -server 192.168.100.5:
get /zk #在容器3获取值
quit
分布式锁
ZooKeeper 分布式锁是基于 临时顺序节点 来实现的,锁可理解为 ZooKeeper 上的一个节点,当需要获取锁时,就在这个锁节点下创建一个临时顺序节点。当存在多个客户端同时来获取锁,就按顺序依次创建多个临时顺序节点,但只有排列序号是第一的那个节点能获取锁成功,其他节点则按顺序分别监听前一个节点的变化,当被监听者释放锁时,监听者就可以马上获得锁。而且用临时顺序节点的另外一个用意是如果某个客户端创建临时顺序节点后,自己意外宕机了也没关系,ZooKeeper 感知到某个客户端宕机后会自动删除对应的临时顺序节点,相当于自动释放锁。

如上图:ClientA 和 ClientB 同时想获取锁,所以都在 locks 节点下创建了一个临时节点 1 和 2,而 1 是当前 locks 节点下排列序号第一的节点,所以 ClientA 获取锁成功,而 ClientB 处于等待状态,这时 ZooKeeper 中的 2 节点会监听 1 节点,当 1节点锁释放(节点被删除)时,2 就变成了 locks 节点下排列序号第一的节点,这样 ClientB 就获取锁成功了。如下是c#代码:
创建 .NET Core 控制台程序
Nuget 安装 ZooKeeperNetEx.Recipes
创建 ZooKeeper Client, ZooKeeprLock代码如下:
namespace ZookeeperDemo
{
using org.apache.zookeeper;
using org.apache.zookeeper.recipes.@lock;
using System;
using System.Diagnostics;
using System.Threading.Tasks;
public class ZooKeeprLock
{
private const int CONNECTION_TIMEOUT = ;
private const string CONNECTION_STRING = "192.168.100.5:2181,192.168.100.5:2182,192.168.100.5:2183"; /// <summary>
/// 加锁
/// </summary>
/// <param name="key">加锁的节点名</param>
/// <param name="lockAcquiredAction">加锁成功后需要执行的逻辑</param>
/// <param name="lockReleasedAction">锁释放后需要执行的逻辑,可为空</param>
/// <returns></returns>
public async Task Lock(string key, Action lockAcquiredAction, Action lockReleasedAction = null)
{
// 获取 ZooKeeper Client
ZooKeeper keeper = CreateClient();
// 指定锁节点
WriteLock writeLock = new WriteLock(keeper, $"/{key}", null); var lockCallback = new LockCallback(() =>
{
lockAcquiredAction.Invoke();
writeLock.unlock();
}, lockReleasedAction);
// 绑定锁获取和释放的监听对象
writeLock.setLockListener(lockCallback);
// 获取锁(获取失败时会监听上一个临时节点)
await writeLock.Lock();
} private ZooKeeper CreateClient()
{
var zooKeeper = new ZooKeeper(CONNECTION_STRING, CONNECTION_TIMEOUT, NullWatcher.Instance);
Stopwatch sw = new Stopwatch();
sw.Start();
while (sw.ElapsedMilliseconds < CONNECTION_TIMEOUT)
{
var state = zooKeeper.getState();
if (state == ZooKeeper.States.CONNECTED || state == ZooKeeper.States.CONNECTING)
{
break;
}
}
sw.Stop();
return zooKeeper;
} class NullWatcher : Watcher
{
public static readonly NullWatcher Instance = new NullWatcher();
private NullWatcher() { }
public override Task process(WatchedEvent @event)
{
return Task.CompletedTask;
}
} class LockCallback : LockListener
{
private readonly Action _lockAcquiredAction;
private readonly Action _lockReleasedAction; public LockCallback(Action lockAcquiredAction, Action lockReleasedAction)
{
_lockAcquiredAction = lockAcquiredAction;
_lockReleasedAction = lockReleasedAction;
} /// <summary>
/// 获取锁成功回调
/// </summary>
/// <returns></returns>
public Task lockAcquired()
{
_lockAcquiredAction?.Invoke();
return Task.FromResult();
} /// <summary>
/// 释放锁成功回调
/// </summary>
/// <returns></returns>
public Task lockReleased()
{
_lockReleasedAction?.Invoke();
return Task.FromResult();
}
} }
}
测试代码:
namespace ZookeeperDemo
{
using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static void Main(string[] args)
{
Parallel.For(, , async (i) =>
{
await new ZooKeeprLock().Lock("locks", () =>
{
Console.WriteLine($"第{i}个请求,获取锁成功:{DateTime.Now},线程Id:{Thread.CurrentThread.ManagedThreadId}");
Thread.Sleep(); // 业务逻辑...
}, () =>
{
Console.WriteLine($"第{i}个请求,释放锁成功:{DateTime.Now},线程Id:{Thread.CurrentThread.ManagedThreadId}");
Console.WriteLine("-------------------------------");
});
});
Console.ReadKey();
}
}
}
运行结果:

关于分布式锁, 我们也可以采用数据库和redis来实现, 各有优缺点。
参考:
How To Install and Configure an Apache ZooKeeper Cluster on Ubuntu 18.04
分布式锁的几种使用方式(redis、zookeeper、数据库)
Docker 下的Zookeeper以及.ne core 的分布式锁的更多相关文章
- ZooKeeper学习笔记四:使用ZooKeeper实现一个简单的分布式锁
作者:Grey 原文地址: ZooKeeper学习笔记四:使用ZooKeeper实现一个简单的分布式锁 前置知识 完成ZooKeeper集群搭建以及熟悉ZooKeeperAPI基本使用 需求 当多个进 ...
- Docker下安装zookeeper(单机 & 集群)
启动Docker后,先看一下我们有哪些选择. 有官方的当然选择官方啦~ 下载: [root@localhost admin]# docker pull zookeeper Using default ...
- ZooKeeper典型应用场景:分布式锁
分布式锁是控制分布式系统之间同步访问共享资源的一种方式.如果不同的系统或是同一个系统的不同主机之间共享了一个或一组资源,那么访问这些资源的时候,往往需要通过一些互斥手段来防止彼此之间的干扰,以保证一致 ...
- Zookeeper--0300--java操作Zookeeper,临时节点实现分布式锁原理
删除Zookeeper的java客户端有 : 1,Zookeeper官方提供的原生API, 2,zkClient,在原生api上进行扩展的开源java客户端 3, 一.Zookeeper原生API ...
- zookeeper学习实践1-实现分布式锁
引言 ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件.它是一个为分布式应用提供一致性服务的软件,提 ...
- zookeeper应用场景练习(分布式锁)
在寻常的高并发的程序中.为了保证数据的一致性.因此都会用到锁.来对当前的线程进行锁定.在单机操作中.非常好做到,比方能够採用Synchronized.Lock或者其它的读写多来锁定当前的线程.可是在分 ...
- Linux下搭建Zookeeper环境
Zookeeper 是 Google 的 Chubby一个开源的实现,是 Hadoop 的分布式协调服务,它包含一个简单的原语集,分布式应用程序可以基于它实现同步服务,配置维护和命名服务等. 其工作原 ...
- ZooKeeper分布式锁的实现原理
七张图彻底讲清楚ZooKeeper分布式锁的实现原理[石杉的架构笔记] 文章转载自:https://juejin.im/post/5c01532ef265da61362232ed#comment(写的 ...
- 利用Zookeeper实现分布式锁
特别提示:本人博客部分有参考网络其他博客,但均是本人亲手编写过并验证通过.如发现博客有错误,请及时提出以免误导其他人,谢谢!欢迎转载,但记得标明文章出处:http://www.cnblogs.com/ ...
随机推荐
- Shell基础 -Linux从入门到精通第九天(非原创)
文章大纲 一.关于shell二.shell进阶(重点)三.学习资料下载四.参考文章 一.关于shell 1. 什么是shell 1.1 shell简介 Shell(外壳) 是一个用 C 语言编写 ...
- using 中写 return 一样会释放using 中对象 但是会在外面定义一个一样的对象 赋值后 释放 最后 return 外面定义的那个对象
static DataTable getDataTable() { ")) { SqlCommand com = new SqlCommand("", con); Sql ...
- eclipse IDE 32位汉化方法及常用软件汉化包寻找办法
今天听说小组开发人员遇到安装eclipse不能汉化问题.了解到其他同事用的都是64位操作系统,这个同事用的32位系统.通常情况下常用软件都有各路大神发的成熟汉化包,不会出现无法安装汉化包的情况. 先找 ...
- PHP使用PhpAnalysis进行分词
1.介绍 PHPAnalysis分词程序使用居于unicode的词库,使用反向匹配模式分词,理论上兼容编码更广泛,并且对utf-8编码尤为方便. 下载地址:http://www.phpbone.com ...
- iview admin动态路由实现
参考 https://blog.csdn.net/weixin_41538490/article/details/93749942
- [windows]c盘瘦身、系统盘清理临时文件、缓存等垃圾文件
前言 虽然现在已经9102年了硬盘空间越来越大越便宜,但win系统用久了系统盘还是会渐渐变小的,公司的电脑系统盘就已经不够用了经常爆红,这个时候两个简单快速高效的办法 1.扩大系统盘空间,可以使用 w ...
- iOS-快速开发直播APP所需第三方SDK
直播SDK 金山云, 推荐 七牛云, 推荐 阿里云(收费) 网易云(收费) 腾讯云(收费) 又拍云 播放SDK IJKPlayer 自定义IJKPlayer,进度条.音量.亮度 短视频SDK 七牛云( ...
- 在eclipse中安装使用lombok插件
Eclipse安装lombok插件 1.下载lombok.jar,lombok.jar官方下载地址:https://projectlombok.org/download 2.双击下载好的lombak. ...
- 套接字编程(TCP)
json模块补充 json保存的格式中,key值一定要用双引号隔开 import json #把字典转成json格式字符串 dic = {'name': 'lqz', 'xx': False, 'yy ...
- 前端 / JavaScript 导出PDF的实践
1.库:jspdf,自己定义一个高宽,如A4的210mm×297mm 2.让设计给背景图(包括:页眉页脚),水印图(背景透明,高宽和你的PDF单页一致)以及很多,能设计给的设计要给,因为在pdf上,排 ...
