当前位置: 首页 > news >正文

漯河住房和城乡建设委员会网站深圳优化排名公司

漯河住房和城乡建设委员会网站,深圳优化排名公司,做的好的排版网站,wordpress自动锚文本介绍 一、zookeeper和redis实现分布式锁的对比 1、redis 分布式场景应用比较广泛,redis分布式锁,其实需要自己不断去尝试获取锁,比较消耗性能;zk分布式锁,获取不到锁,注册个监听器即可,不需要不…

介绍

一、zookeeper和redis实现分布式锁的对比
1、redis 分布式场景应用比较广泛,redis分布式锁,其实需要自己不断去尝试获取锁,比较消耗性能;zk分布式锁,获取不到锁,注册个监听器即可,不需要不断主动尝试获取锁,性能开销较小

2、如果是redis获取锁的那个客户端bug了或者挂了,那么只能等待超时时间之后才能释放锁;而zk的话,因为创建的是临时znode,只要客户端挂了,znode就没了,此时就自动释放锁。

二、zookeeper分布式锁原理
这个主要得益于ZooKeeper为我们保证了数据的强一致性。锁服务可以分为两类,一个是保持独占,另一个是控制时序。

1、保持独占,就是所有试图来获取这个锁的客户端,最终只有一个可以成功获得这把锁。通常的做法是把zk上的一个znode看作是一把锁,通过create znode的方式来实现。所有客户端都去创建 /mylock节点,最终成功创建的那个客户端也即拥有了这把锁。

2、控制时序,就是所有试图来获取这个锁的客户端,最终都会被安排执行,只是有个全局时序。做法和上面基本类似,只是这里 /mylock已经预先存在,客户端在它下面创建临时顺序节点。Zk的父节点(/mylock)维持一份sequence,保证子节点创建的时序性,从而也形成了每个客户端的全局时序。

三、zookeeper实现分布式锁的方式
(1)方式一:创建一个临时节点

        在需要获取排他锁时,所有的客户端都会试图通过调用 create -e 接口,在/mylock节点下创建临时子节点/mylock/lock。 ZooKeeper会保证在所有的客户端中,最络只有一个客户端能够创建成功,那么就可以认为该客户端获取了锁。

        同时,所有没有获取到锁的客户端就需要对 /mylock/lock 节点上注册一个Watcher监听,以便实时监听到lock节点的变更情况。如果节点被使用完删除了,zookeeper要向所有监听者发送通知,这会阻塞其他操作,并且会导致所有客户端来争抢锁,这种情况称为“羊群效应”,试想一下,如果监听者众多的话,会拖累性能。

(2)方式二:创建临时顺序节点

create -s -e /mylock/lock-data
1、每个试图加锁的客户端都会创建一个临时顺序节点 /mylock/lock-xxxxx,并且zk可以保证序号连续且唯一;

2、然后获取 /mylock/ 下的所有子节点,并按从小到大排序list;

3、判断最小节点是不是自己,如果是证明你就获取锁了,可以去处理业务逻辑了;

4、如果不是,获取到list中你的上一个节点名称(不一定是 -1 的那一个,因为此时它对应的客户端有可能主动放弃了),对其实施监听操作 get /mylock/lock-xxxxx watch 如果get监听失败了,说明节点已经别清除了,重复 2,3 直到监听成功或者获取锁,如果监听成功,就在这里阻塞,等待通知;

5、如果通知过来了,重复 2,3,4 的步骤,直到获取锁,因为上一个节点被释放的原因并不一定是它得到锁-使用完-释放,有可能是客户端断开连接了;

6、锁用完后记得主动清除,不然要等到心跳检测的时候才会清除。

优点:具备高可用、可重入、阻塞锁特性,可解决失效死锁问题。

缺点:因为需要频繁的创建和删除节点,性能上不如Redis方式。

四、安装PHP的zookeeper扩展
虽然ZooKeeper是一个Java应用程序,但C也可以使用。所以安装PHP的扩展,则首先安装zookeeper的C扩展支持

1、安装Zookeeper C扩展支持
示例中使用的zookeeper3.4.12版本

cd /usr/local/zk3.4/src/c
 
#编译C扩展,由于zookeeper解压即可用,这里下载源码主要是了编译C扩展,为后面安装PHP的扩展用
./configure --prefix=/usr/local/zk3.4/
make
make install
2、安装php的zookeeper扩展
zookeeper的PHP扩展可以在pecl上下载,也可以在github上下载,但有人说pecl上有bug。

git clone https://github.com/php-zookeeper/php-zookeeper.git
cd php-zookeeper
/usr/local/php7.4/bin/phpize
./configure --with-libzookeeper-dir=/usr/local/zk3.4/ --with-php-config=/usr/local/php7.4/bin/php-config
make && make install
 
vim php.ini
extension=zookeeper
/etc/php-fpm restart
五、PHP+zookeeper实现分布式锁示例
<?php
 
/*
 * zookeeper 类属性常量参考
 * https://www.php.net/manual/zh/class.zookeeper.php#zookeeper.class.constants.perms
 */
class zkCli {
    protected static $zk;
    protected static $myNode;
    protected static $isNotifyed;
    protected static $root;
 
    public static function getZkInstance($conf, $root){
        try{
 
            if(isset(self::$zk)){
                return self::$zk;
            }
 
            $zk = new \Zookeeper($conf['host'] . ':' . $conf['port']);
            if(!$zk){
                throw new \Exception('connect zookeeper error');
            }
 
            self::$zk = $zk;
            self::$root = $root;
 
            return $zk;
        } catch (\ZookeeperException $e){
            die($e->getMessage());
        } catch (\Exception $e){
            die($e->getMessage());
        }
    }
 
    // 获取锁
    public static function tryGetDistributedLock($lockKey, $value){
        try{
            // 创建根节点
            self::createRootPath($value);
            // 创建临时顺序节点
            self::createSubPath(self::$root . $lockKey, $value);
            // 获取锁
            return self::getLock();
 
        } catch (\ZookeeperException $e){
            return false;
        } catch (\Exception $e){
            return false;
        }
    }
 
    // 释放锁
    public static function releaseDistributedLock(){
        if(self::$zk->delete(self::$myNode)){
            return true;
        }else{
            return false;
        }
    }
 
    public static function createRootPath($value){
        $aclArray = [
            [
                   'perms'  => Zookeeper::PERM_ALL,
                    'scheme' => 'world',
                    'id'     => 'anyone',
            ]
        ];
        
          // 判断根节点是否存在
        if(false == self::$zk->exists(self::$root)){
            // 创建根节点
            $result = self::$zk->create(self::$root, $value, $aclArray);
            if(false == $result){
                throw new \Exception('create '.self::$root.' fail');
            }
        }
            
        return true;
    }
 
    public static function createSubPath($path, $value){
        // 全部权限
        $aclArray = [
            [
                'perms'  => Zookeeper::PERM_ALL,
                'scheme' => 'world',
                'id'     => 'anyone',
            ]
        ];
        /**
         * flags :
         * 0 和 null 永久节点,
         * Zookeeper::EPHEMERAL临时,
         * Zookeeper::SEQUENCE顺序,
         * Zookeeper::EPHEMERAL | Zookeeper::SEQUENCE 临时顺序
         */
        self::$myNode = self::$zk->create($path, $value, $aclArray, Zookeeper::EPHEMERAL | Zookeeper::SEQUENCE);
        if(false == self::$myNode){
            throw new \Exception('create -s -e '.$path.' fail');
        }
        echo 'my node is ' . self::$myNode.'-----------'.PHP_EOL;
 
        return true;
    }
 
    public function getLock(){
        // 获取子节点列表从小到大,显然不可能为空,至少有一个节点
        $res = self::checkMyNodeOrBefore();
        if($res === true){
            return true;
        }else{
            self::$isNotifyed = false;// 初始化状态值
            // 考虑监听失败的情况:当我正要监听before之前,它被清除了,监听失败返回 false
            $result = self::$zk->get($res, [zkCli::class, 'watcher']);
            while(!$result){
                $res1 = self::checkMyNodeOrBefore();
                if($res1 === true){
                    return true;
                }else{
                    $result = self::$zk->get($res1, [zkCli::class, 'watcher']);
                }
            }
 
            // 阻塞,等待watcher被执行,watcher执行完回到这里
            while(!self::$isNotifyed){
                echo '.';
                usleep(500000); // 500ms
            }
            
            return true;
        }
    }
 
    /**
     * 通知回调处理
     * @param $type 变化类型 Zookeeper::CREATED_EVENT, Zookeeper::DELETED_EVENT, Zookeeper::CHANGED_EVENT
     * @param $state
     * @param $key 监听的path
     */
    public static function watcher($type, $state, $key){
        echo PHP_EOL.$key.' notifyed ....'.PHP_EOL;
        self::$isNotifyed = true;
        self::getLock();
    }
 
    public static function checkMyNodeOrBefore(){
        $list = self::$zk->getChildren(self::$root);
        sort($list);
        $root = self::$root;
        array_walk($list, function(&$val) use ($root){
            $val = $root . '/' . $val;
        });
 
        if($list[0] == self::$myNode){
            echo 'get locak node '.self::$myNode.'....'.PHP_EOL;
            return true;
        }else{
            // 找到上一个节点
            $index = array_search(self::$myNode, $list);
            $before = $list[$index - 1];
            echo 'before node '.$before.'.........'.PHP_EOL;
            return $before;
        }
    }
}
 
 
function zkLock($resourceId){
    $conf = ['host'=>'127.0.0.1', 'port'=>2181];
    $root = '/lockKey_' . $resourceId;
    $lockKey = '/lock_';
    $value = 'a';
 
    $client = zkCli::getZkInstance($conf, $root);
    $re = zkCli::tryGetDistributedLock($lockKey, $value);
 
    if($re){
        echo 'get lock success'.PHP_EOL;
    }else{
        echo 'get lock fail'.PHP_EOL;
        return ;
    }
 
    try {
 
        doSomething();
 
    } catch(\Exception $e) {
 
        echo $e->getMessage() . PHP_EOL;
 
    } finally {
 
        $re = zkCli::releaseDistributedLock();
        if($re){
            echo 'release lock success'.PHP_EOL;
        }else{
            echo 'release lock fail'.PHP_EOL;
        }
 
        return ;
    }
}
 
function doSomething(){
    $n = rand(1, 20);
    switch($n){
        case 1: 
            sleep(15);// 模拟超时
            break;
        case 2:
            throw new \Exception('system throw message...');// 模拟程序中止
            break;
        case 3:
            die('system crashed...');// 模拟程序崩溃
            break;
        default:
            sleep(13);// 正常处理过程
    }
}
 
// 执行
zkLock(0);


文章转载自:
http://catalufa.qpnb.cn
http://vehemently.qpnb.cn
http://crinoline.qpnb.cn
http://zygogenesis.qpnb.cn
http://wogland.qpnb.cn
http://merci.qpnb.cn
http://transmit.qpnb.cn
http://nondairy.qpnb.cn
http://pneumatotherapy.qpnb.cn
http://thermohaline.qpnb.cn
http://utricle.qpnb.cn
http://blockbusting.qpnb.cn
http://disport.qpnb.cn
http://excommunicable.qpnb.cn
http://spanish.qpnb.cn
http://harpins.qpnb.cn
http://maghemite.qpnb.cn
http://baneful.qpnb.cn
http://neither.qpnb.cn
http://cervantite.qpnb.cn
http://winterbound.qpnb.cn
http://klooch.qpnb.cn
http://idiorrhythmism.qpnb.cn
http://cacorhythmic.qpnb.cn
http://medial.qpnb.cn
http://paracasein.qpnb.cn
http://engaging.qpnb.cn
http://vfat.qpnb.cn
http://trihydrate.qpnb.cn
http://benefit.qpnb.cn
http://covering.qpnb.cn
http://blot.qpnb.cn
http://untraveled.qpnb.cn
http://crawdad.qpnb.cn
http://apartheid.qpnb.cn
http://baldhead.qpnb.cn
http://canoness.qpnb.cn
http://dogger.qpnb.cn
http://bethel.qpnb.cn
http://pieplant.qpnb.cn
http://hesperian.qpnb.cn
http://pugnacity.qpnb.cn
http://hypnotherapy.qpnb.cn
http://fingersmith.qpnb.cn
http://conterminal.qpnb.cn
http://echolocate.qpnb.cn
http://babesiasis.qpnb.cn
http://coinstitutional.qpnb.cn
http://quarry.qpnb.cn
http://cpa.qpnb.cn
http://foeman.qpnb.cn
http://inconsecutive.qpnb.cn
http://beebee.qpnb.cn
http://prissie.qpnb.cn
http://hysterectomy.qpnb.cn
http://isopterous.qpnb.cn
http://conversus.qpnb.cn
http://ecstatic.qpnb.cn
http://angekok.qpnb.cn
http://krone.qpnb.cn
http://noshery.qpnb.cn
http://monosyllable.qpnb.cn
http://centricity.qpnb.cn
http://indrawn.qpnb.cn
http://frailly.qpnb.cn
http://houseful.qpnb.cn
http://rhizomatic.qpnb.cn
http://gppm.qpnb.cn
http://grana.qpnb.cn
http://myriapodan.qpnb.cn
http://symphily.qpnb.cn
http://hoosh.qpnb.cn
http://arabist.qpnb.cn
http://maypole.qpnb.cn
http://coronograph.qpnb.cn
http://cowrie.qpnb.cn
http://barghest.qpnb.cn
http://throwoff.qpnb.cn
http://senti.qpnb.cn
http://wolffish.qpnb.cn
http://plow.qpnb.cn
http://hyperphysically.qpnb.cn
http://histopathology.qpnb.cn
http://crizzle.qpnb.cn
http://abattis.qpnb.cn
http://accommodation.qpnb.cn
http://subbreed.qpnb.cn
http://limn.qpnb.cn
http://unscripted.qpnb.cn
http://judiciary.qpnb.cn
http://shamoy.qpnb.cn
http://israeli.qpnb.cn
http://snowcap.qpnb.cn
http://incommensurability.qpnb.cn
http://eighthly.qpnb.cn
http://diopside.qpnb.cn
http://nicotine.qpnb.cn
http://outrelief.qpnb.cn
http://caravaneer.qpnb.cn
http://usurpatory.qpnb.cn
http://www.hrbkazy.com/news/84610.html

相关文章:

  • 宁波网站推广工作室电话站长工具
  • 网站建设原则应考虑哪些软文写作500字
  • 政府做网站wordpress自助建站
  • 网页制作大概需要多少钱东莞百度推广排名优化
  • 邯郸做网站xy0310十大广告联盟
  • 沈阳商城网站建设网站seo公司
  • vs2013可以做网站么鲜花网络营销推广方案
  • 深圳自助建站网站营销型网站是什么意思
  • 做鞋的垂直网站seo是什么意思 seo是什么职位
  • 宁波网站推广优化收费情况站长工具seo综合查询官网
  • 如何利用路由建设网站营销型网站建设公司价格
  • 临沂哪里做网站网店推广方案范文
  • 南昌网优化seo公司宁波seo网络推广定制
  • wordpress写代码编辑器快速优化关键词排名
  • 公司网站建设考核湖南靠谱seo优化公司
  • 淘客做网站网络优化工程师需要学什么
  • 有哪些网站是做视频的网络营销公司招聘
  • 怎麽用dw做网站轮播海报辽源seo
  • javascript代码大全高级seo培训
  • 建设互联网站是什么杭州关键词排名提升
  • 网站备案与服务器seo什么意思简单来说
  • 优必选网站企业网站优化技巧
  • 雄安 网站建设抖音推广渠道有哪些
  • 陕西省住房城乡建设厅网站网络营销师证书怎么考
  • 做网站 不是计算机专业宁波网络推广方法
  • 凡科建站做的网站有什么短板长春关键词搜索排名
  • 山西省新农村建设网站许昌网站seo
  • 一个网站怎么做镜像站seo技术培训江门
  • 温州网站排名优化外链工具xg
  • 网站谷歌seo做哪些武汉网络seo公司