Zookeeper Practical Solution: (7) distributed lock

Source: Internet
Author: User

1. Basic Introduction

Distributed locks are a way to control shared resources between distributed systems, and they need to be mutually exclusive to prevent mutual interference to ensure consistency.

The lock service can be completed with the strong consistency of zookeeper. The official document of zookeeper is to enumerate the two types of locks. Exclusive locks and shared locks.

Exclusive locks guarantee that there is only one process or resource read-write permission at any time. A shared lock can have multiple reads at the same time, but at most one write at a time, read and write are mutually exclusive.

2. Scenario Analysis

We are ready to implement mutually exclusive lock, according to the official website of the idea, given a lock path, such as/lock, all the process to apply for this lock in the/lock folder to create a/lock/lock-temporary sequence node, and monitor the/lock child node change events. When a child node sends a change with Get_children () gets a list of child nodes, assuming the discovery process finds itself having the smallest ordinal number, the lock is obtained.

When the processing business is completed, the lock needs to be released and only the temporary node needs to be deleted. Simply put, the process that has the smallest sequence number always gets the lock.

3. Scene Practice

Using a lock has two main functions, which is lock or unlock . Defined as

    • Lock *lock(zhandle_t *zkhandle,const char *path)
      The lock function has two parameters, one is the handle returned by Zookeeper_init Zkhandle, and the other is the path to the lock, assuming that success returns a lock's struct pointer. And get the lock at the same time, otherwise null is returned.
    • int unlock(zhandle_t *zkhandle,Lock * *lock)
      The unlock function also has two parameters. One is the handle returned by Zookeeper_init Zkhandle, and the other is a pointer to the struct pointer returned by the lock function.

The next step is to look at the detailed implementation.

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 : Responsible for the initialization of the lock. The primary feature is the temporary sequence node that is responsible for creating the {path} node already {path}/lock-.

      {path} assumes the existence is no longer created.

    • try_lock : Attempt to lock, this function does not wait, failure and success are returned immediately. Its main function is to get a list of the child nodes of {path} and see if you are a node with a minimum serial number. The assumption is that 1 is returned, otherwise 0 is returned;

lockAfter the function initializes the lock, it continues to attempt to lock until it succeeds. Though I have done so. But too simple and rude (haha). Suppose you can't get a lock. Persistent will clog up in the lock function.

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;}


unlockThe function is easy. is create_lock to delete the temporary sequence nodes that were created in.

Next look at the function of the simulation program.

>./mylock-husage: [Mylock] [-h]  [-P path][-s Ip:port]-         h Show help-        P lock Path-        s zookeeper server ip:portfor Example:    mylock-s 172.17.0.36:2181-p/lock


The simulation program has 3 options.

Of
-s: The ip:port of the server for zookeeper.
-p: The path to the lock.

By executing multiple mylock programs at the same time, you can see how the locks are acquired between each program.

The final is the complete code:

#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_un          safe,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);    Set the log level to avoid some other information 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;}



Copyright notice: This article blog original articles, blogs, without consent, may not be reproduced.

Zookeeper Practical Solution: (7) distributed lock

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.