用Memcache实现分布式的锁服务

一般情况下我们都用Memcache作为一个分布式的key/value缓存服务器,其实Memcache也可以实一些外门邪道的功能比如作为分布式锁来用。

原理其实非常简单就是memecach_add的时候,如果添加的key已经存在那么后面的添加就会失败。设想在高并发的场景下,如果存在被竞争的资源,我们就可以利用这个小trick来对资源加锁。知道了原理实现起来非常简单,下面是我初步实现的代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
<?php

/**
 * 锁服务(用Memcache模拟锁)
 * Author: tomheng<zhm20070928@gmail.com>
 * gist: https://gist.github.com/tomheng/6149779
 */


class Lock{

    private $mc = null;
    private $key_prefix = "memcache_lock_service_key_";
    private $all_lock_names = array();
    private $expiration = 60; //one min
    private $max_block_time = 15; //最长的阻塞时间
    /**
     * [__construct description]
     */

    public function __construct(){
        if(function_exists('memcache_init')){
            $this->mc = memcache_connect('memcache_host', 11211);
        }
    }

    /**
     * [get_key description]
     * @param  [type] $name [description]
     * @return [type]       [description]
     */

    private function get_key($name){
        $key = $this->key_prefix.$name;
        return $key;
    }

    /**
     * 捕获锁
     * @param  [type] $name [description]
     * @return [type]       [description]
     */

    public  function begin($name, $block = true)
    {
        if(!$this->mc || !$name){
            return false;
        }
        $max_block_time = $this->max_block_time;
        $key = $this->get_key($name);
        do{
            $re = memcache_add($this->mc, $key, 1, false, $this->expiration);
            if($re == true){
                $this->all_lock_names[$name] = 1;
                //$this->debug();
                break;
            }else{
                //dolog('Lock failed '.$name);
            }
            //echo '#'.PHP_EOL;
            //sleep(1);
        }while($block && $max_block_time-- && !sleep(1));
        return $re;
    }

    /**
     * 释放锁
     */

    public function release($name){
        if(!$this->mc || !$name){
            return false;
        }
        $key = $this->get_key($name);
        $re = memcache_delete($this->mc, $key);
        if($re == true){
            unset($this->all_lock_names[$name]);
        }
        return $re;
    }

    /**
     * 释放所有的锁
     */

    public function __destruct(){
        if(!$this->mc){
            return false;
        }
        foreach ($this->all_lock_names as $name => $value) {
            # code...
            $this->release($name);
        }
    }

    /**
     * 调试
     * @return [type] [description]
     */

    public function debug(){
        var_dump($this->all_lock_names);
        foreach ($this->all_lock_names as $name => $value) {
            $key = $this->get_key($name);
            if($this->mc){
                $value = memcache_get($this->mc, $key);
            }else{
                $value = "no such lock ";
            }
            echo "Lock name:$key, value:{$value}".PHP_EOL;
        }
    }
}

用Memcache实现分布式的锁服务》有1个想法

  1. Pingback引用通告: 利用分布式缓存实现分布式锁 | 求知若饥,虚心若愚

评论已关闭。