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/ ...
随机推荐
- WPE 过滤器 高级滤镜
与普通滤镜区别就是: 普通滤镜固定位置 高级滤镜固定数值 普通滤镜 指定位置1~6,对应发送数据的固定1~6字节 高级滤镜 首先,勾选高级-自发现有连锁位置 记得,偏移001对应修改000位置,也可称 ...
- Kubernetes概念之RC
感觉自己浪费了一年的时间,种一棵树最好的时间是十年前,还有就是现在,虽然这颗树种了又种,种了又种,这次真的要种了...... 本文通过<Kubernetes权威指南>的概念部分学习总结 ...
- HTML5-表单 自带验证
表单语法<form method="post"(规定如何发送表单数据 常用值:get|post) action="result.html">(表示向 ...
- 给大家推荐一个nginx.conf文件格式生成的网站
特别好用: 根据选择自定义nginx.conf的配置: https://nginxconfig.io/?0.php=false&0.python&php_server=%2Fvar%2 ...
- 编写体面的UI测试
--01-- PageObject简介 PageObject是编写UI测试时的一种模式.简而言之,你可以将所有知道页面细节的部分放入到这个对象上,对于编写测试的人来说,一个PageObject代表 ...
- Centos7离线部署docker
下载docker离线包 wget https://download.docker.com/linux/static/stable/x86_64/docker-19.03.5.tgz 解压 tar -x ...
- USACO Superprime Rib
洛谷 P1218 [USACO1.5]特殊的质数肋骨 Superprime Rib 洛谷传送门 JDOJ 1673: Superprime Rib JDOJ传送门 题目描述 农民约翰的母牛总是产生最好 ...
- 2016 ACM/ICPC亚洲区沈阳站
A B C D E F G H I J K L M O O O $\varnothing$ $\varnothing$ $\varnothing$ $\varnothing$ $\varnothi ...
- LRU Algorithm Gym - 102394L (HASH)
LRU Algorithm \[ Time Limit: 1000 ms\quad Memory Limit: 524288 kB \] 题意 给出 \(n\) 个数字和 \(m\) 次查询. 每次询 ...
- Datagrip 2017.2 激活
解决方法 参考网址:https://jetbrains-server.ru/2017/03/31/datagrip-2016-2017-activation/page/2/ 亲测使用http://id ...