1.基本介绍

分布式锁是控制分布式系统之间同步訪问共享资源的一种方式,须要相互排斥来防止彼此干扰来保证一致性。

利用Zookeeper的强一致性能够完毕锁服务。Zookeeper的官方文档是列举了两种锁。独占锁和共享锁。

独占锁保证不论什么时候都仅仅有一个进程能或者资源的读写权限。共享锁能够同一时候有多个读,可是同一时刻最多仅仅能有一个写,读和写是相互排斥的。

2.场景分析

我们准备来实现相互排斥的锁,依照官网的思路,给定一个锁的路径,如/Lock,全部要申请这个锁的进程都在/Lock文件夹下创建一个/Lock/lock-的暂时序列节点,并监控/Lock的子节点变化事件。当子节点发送变化时用get_children()获取子节点的列表,假设发现进程发现自己拥有最小的一个序号,则获得锁。

处理业务完成后须要释放锁,此时仅仅须要删除该暂时节点就可以。简单来说就是永远是拥有最小序号的进程获得锁。

3.场景实践

使用锁有两个主要的函数,就是lockunlock.定义为

  • Lock *lock(zhandle_t *zkhandle,const
    char *path)


    lock函数有两个參数,一个是zookeeper_init返回的句柄zkhandle,还有一个是锁的路径,假设成功则返回一个Lock的结构体指针。并同一时候获得锁,否则返回NULL。
  • int unlock(zhandle_t *zkhandle,Lock * *lock)

    unlock函数也有两个參数。一个是zookeeper_init返回的句柄zkhandle,还有一个是lock函数返回的结构体指针的指针

接下来在看详细的实现。

Lock *lock(zhandle_t *zkhandle,const char *path)
{
Lock *lock = create_lock(zkhandle,path);
if(lock != NULL){
while(try_lock(zkhandle,lock) == 0){
sleep(1);
}
}else{
fprintf(stderr,"error when create lock %s.\n",path);
} return lock;
}

  • create_lock:负责锁的初始化。主要功能是负责创建{path}的节点已经{path}/lock-的暂时序列节点。

    {path}假设存在则不再创建。

  • try_lock:尝试加锁,这个函数不会等待,失败和成功都马上返回。其主要功能是获取{path}的子节点列表,并查看自己是否是拥有最小序列号的节点。假设是则返回1,否则返回0;

lock函数初始化锁后,会持续的尝试加锁,直到成功。尽管我是这样实现的。可是过于简单粗暴(哈哈)。假设拿不到锁的话。持续就会堵塞在lock函数。

int unlock(zhandle_t *zkhandle,Lock * *lock)
{
if(*lock){
int ret = zoo_delete(zkhandle,(*lock)->selfpath,-1);
if(ret != ZOK){
fprintf(stderr,"error when release lock %s.\n",(*lock)->selfpath);
}
free(*lock);
*lock = NULL; return ret;
} return ZOK;
}

unlock函数就很easy了。就是将create_lock中创建的暂时序列节点删除就能够了。

接下来在看下模拟程序的功能。

> ./mylock -h
Usage : [mylock] [-h] [-p path][-s ip:port]
-h Show help
-p lock path
-s zookeeper server ip:port
For example:
mylock -s 172.17.0.36:2181 -p /Lock

模拟程序有3个选项。

当中

-s:为Zookeeper的server的ip:port.

-p: 为锁的路径。

分别同一时候执行多个mylock程序,就能够看到各个程序之间是怎样获取锁的了。

最后是完整的代码:

#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include"zookeeper.h"
#include"zookeeper_log.h" char g_host[512]= "172.17.0.36:2181";
char g_path[512]= "/Lock"; typedef struct Lock
{
char lockpath[1024];
char selfpath[1024];
}Lock; void print_usage();
void get_option(int argc,const char* argv[]); /**********unitl*********************/
void print_usage()
{
printf("Usage : [mylock] [-h] [-p path][-s ip:port] \n");
printf(" -h Show help\n");
printf(" -p lock path\n");
printf(" -s zookeeper server ip:port\n");
printf("For example:\n");
printf(" mylock -s172.17.0.36:2181 -p /Lock\n");
} void get_option(int argc,const char* argv[])
{
extern char *optarg;
int optch;
int dem = 1;
const char optstring[] = "hp:s:"; while((optch = getopt(argc , (char * const *)argv , optstring)) != -1 )
{
switch( optch )
{
case 'h':
print_usage();
exit(-1);
case '?':
print_usage();
printf("unknown parameter: %c\n", optopt);
exit(-1);
case ':':
print_usage();
printf("need parameter: %c\n", optopt);
exit(-1);
case 's':
strncpy(g_host,optarg,sizeof(g_host));
break;
case 'p':
strncpy(g_path,optarg,sizeof(g_path));
break;
default:
break;
}
}
} Lock *create_lock(zhandle_t *zkhandle,const char *path)
{
char path_buffer[512]={0};
int bufferlen = sizeof(path_buffer);
Lock * lock = NULL; int ret = zoo_exists(zkhandle,path,0,NULL);
if(ret != ZOK){
ret = zoo_create(zkhandle,path,"1.0",strlen("1.0"),
&ZOO_OPEN_ACL_UNSAFE,0,
path_buffer,bufferlen);
if(ret != ZOK){
fprintf(stderr,"failed to create the path %s!\n",path);
}else{
printf("create path %s successfully!\n",path);
}
}
if(ret == ZOK){
char child_path[512];
sprintf(child_path,"%s/lock-",path);
ret = zoo_create(zkhandle,child_path,"1.0",strlen("1.0"),
&ZOO_OPEN_ACL_UNSAFE,ZOO_SEQUENCE|ZOO_EPHEMERAL,
path_buffer,bufferlen);
if(ret != ZOK){
fprintf(stderr,"failed to create the path %s!\n",path);
}else{
printf("create path %s successfully!\n",path);
}
}
if(ret == ZOK){
lock = (Lock *)malloc(sizeof(Lock)); strcpy(lock->lockpath,path);
strcpy(lock->selfpath,path_buffer);
} return lock;
} int try_lock(zhandle_t *zkhandle,Lock *lock)
{
struct String_vector children;
int i = 0;
int ret = zoo_get_children(zkhandle,lock->lockpath,0,&children); if(ret != ZOK){
fprintf(stderr,"error when get children of path %s\n",lock->lockpath);
ret = -1;
}else{
char *myseq = rindex(lock->selfpath,'/');
if (myseq != NULL) myseq += 1; ret = 1;
for(i = 0; i < children.count; ++i){
if(strcmp(children.data[i],myseq) < 0){
ret = 0;
break;
}
} for(i = 0; i < children.count; ++i){
free(children.data[i]);
children.data[i] = NULL;
}
} return ret;
} Lock *lock(zhandle_t *zkhandle,const char *path)
{
Lock *lock = create_lock(zkhandle,path);
if(lock != NULL){
while(try_lock(zkhandle,lock) == 0){
sleep(1);
}
}else{
fprintf(stderr,"error when create lock %s.\n",path);
} return lock;
} int unlock(zhandle_t *zkhandle,Lock * *lock)
{
if(*lock){
int ret = zoo_delete(zkhandle,(*lock)->selfpath,-1);
if(ret != ZOK){
fprintf(stderr,"error when release lock %s.\n",(*lock)->selfpath);
}
free(*lock);
*lock = NULL; return ret;
} return ZOK;
} int main(int argc, const char *argv[])
{
int timeout = 30000;
char path_buffer[512];
int bufferlen=sizeof(path_buffer); zoo_set_debug_level(ZOO_LOG_LEVEL_WARN); //设置日志级别,避免出现一些其它信息 get_option(argc,argv); zhandle_t* zkhandle = zookeeper_init(g_host,NULL, timeout, 0, (char *)"lock Test", 0); if (zkhandle ==NULL)
{
fprintf(stderr, "Error when connecting to zookeeper servers...\n");
exit(EXIT_FAILURE);
} int ret = zoo_exists(zkhandle,g_path,0,NULL);
if(ret != ZOK){
ret = zoo_create(zkhandle,g_path,"1.0",strlen("1.0"),
&ZOO_OPEN_ACL_UNSAFE,0,
path_buffer,bufferlen);
if(ret != ZOK){
fprintf(stderr,"failed to create the path %s!\n",g_path);
}else{
printf("create path %s successfully!\n",g_path);
}
} if(ret == ZOK ){
Lock *mylock = lock(zkhandle,g_path); if(mylock){
printf("get lock of %s.\n",g_path);
printf("self path is %s.\n",mylock->selfpath); printf("do something....\n");
getchar(); unlock(zkhandle,&mylock);
}
} zookeeper_close(zkhandle); return 0;
}

版权声明:本文博客原创文章,博客,未经同意,不得转载。

ZooKeeper实践方案:(7) 分布式锁的更多相关文章

  1. Zookeeper是如何实现分布式锁的

    [toc] Zookeeper是如何实现分布式锁的 标签 : Zookeeper 分布式 实现分布式锁要考虑的重要问题 1. 三个核心要素 加锁, 解锁, 锁超时 2. 三个问题 要保证原子性操作, ...

  2. zookeeper学习实践1-实现分布式锁

    引言 ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件.它是一个为分布式应用提供一致性服务的软件,提 ...

  3. 基于zookeeper或redis实现分布式锁

    前言 在分布式系统中,分布式锁是为了解决多实例之间的同步问题.例如master选举,能够获取分布式锁的就是master,获取失败的就是slave.又或者能够获取锁的实例能够完成特定的操作. 目前比较常 ...

  4. zookeeper适用场景:分布式锁实现

    问题导读:1.zookeeper如何实现分布式锁?2.什么是羊群效应?3.zookeeper如何释放锁? 在zookeeper应用场景有关于分布式集群配置文件同步问题的描述,设想一下如果有100台机器 ...

  5. 服务注册中心之ZooKeeper系列(三) 实现分布式锁

    通过ZooKeeper的有序节点.节点路径不回重复.还有节点删除会触发Wathcer事件的这些特性,我们可以实现分布式锁. 一.思路 zookeeper中创建一个根节点Locks,用于后续各个客户端的 ...

  6. zookeeper【5】分布式锁

    我们常说的锁是单进程多线程锁,在多线程并发编程中,用于线程之间的数据同步,保护共享资源的访问.而分布式锁,指在分布式环境下,保护跨进程.跨主机.跨网络的共享资源,实现互斥访问,保证一致性. 架构图: ...

  7. 基于ZooKeeper的三种分布式锁实现

    [欢迎关注公众号:程序猿讲故事 (codestory),及时接收最新文章] 今天介绍基于ZooKeeper的分布式锁的简单实现,包括阻塞锁和非阻塞锁.同时增加了网上很少介绍的基于节点的非阻塞锁实现,主 ...

  8. Zookeeper绍二(分布式锁介)

    一.为什么会有分布式锁? 在多线程环境下,由于上下文的切换,数据可能出现不一致的情况或者数据被污染,我们需要保证数据安全,所以想到了加锁. 所谓的加锁机制呢,就是当一个线程访问该类的某个数据时,进行保 ...

  9. Zookeeper实践方案:(4)命名服务

    1.基本介绍 命名服务是指通过指定的名字来获取资源或者服务的地址,提供者的信息.利用Zookeeper非常easy创建一个全局的路径,而这个路径就能够作为一个名字.它能够指向集群中的集群.提供的服务的 ...

随机推荐

  1. The tempfile module

    The tempfile module The tempfile module This module allows you to quickly come up with unique names ...

  2. Spring中继承配置的注入方法

    (1)两个java类.一个父类一个字类 package com.lc.inherit; /* * 这里是父类 */ public class Student { protected String na ...

  3. autoit 处理文件上传弹出框,并在JAVA中调用

    Java  代码 //定义exe 文件存放的绝对路径 File file2 = new File("."); String command = file2.getCanonical ...

  4. hdu4289(最小割)

    传送门:Control 题意:有n个城市,有个小偷想从其中一个城市逃到另一个城市,警察想要堵截这个小偷,知道了在每个城市堵截的成本,问如何安排在哪些城市堵截可以使得小偷一定会被抓住,而且成本最低. 分 ...

  5. uva 1434 - YAPTCHA(数论)

    题目链接:uva 1434 - YAPTCHA 题目大意:给定n和k,求题目中给定的式子S(n). 解题思路:威尔逊定理,x为素数时有,((x−1)!+1)%x==0,所以对于本题.假设3*k+7为素 ...

  6. aix 下 实现goldengate 随os启动而自己主动启动的脚本

    aix 下 实现goldengate 随os启动而自己主动启动的脚本: 1.用oracle用户建立/u01/info.txt,文件内容例如以下: sh date start mgr 2.chmod + ...

  7. TMS320F28335项目开发记录5_28335之CCS编程基础

    CCS开发环境已经为我们封装好了很多片内外设寄存器的结构体,我们仅仅须要包括对应的官方的头文件就能够使用了,那么它的内部详细是怎样实现的呢? 以下来一个典型的样例: 1.使用结构体和联合体 A.用st ...

  8. c++一些语法模板

    函数模板特 template <class T> int compare(T v1,T v2) { if(v1<v2) return -1; else if(v1>v2) re ...

  9. Android从raw、assets、SD卡中获取资源文件内容

    先顺带提一下,raw文件夹中的文件会和project一起经过编译,而assets里面的文件不会~~~   另外,SD卡获取文件需要权限哦! //从res文件夹中的raw 文件夹中获取文件并读取数据 p ...

  10. 有向无环图(DAG)的最小路径覆盖

    DAG的最小路径覆盖 定义:在一个有向图中,找出最少的路径,使得这些路径经过了所有的点. 最小路径覆盖分为最小不相交路径覆盖和最小可相交路径覆盖. 最小不相交路径覆盖:每一条路径经过的顶点各不相同.如 ...