PHP / 开源社区 · 2018/03/22 2

php+zookeeper的curd操作

上一篇讲了一些安装流程,这篇来看下常用函数

http://php.net/manual/zh/book.zookeeper.php

我们用的比较多的应该是

public function connect( $host, $watcher_cb = null, $recv_timeout = 10000) {}

public function create( $path, $value, $acl, $flags = null ) {}
<?php
$zookeeper = new Zookeeper('locahost:2181');
$aclArray = array(
  array(
    'perms'  => Zookeeper::PERM_ALL,
    'scheme' => 'world',
    'id'     => 'anyone',
  )
);
$path = '/path/to/newnode';
$realPath = $zookeeper->create($path, null, $aclArray);
if ($realPath)
  echo $realPath;
else
  echo 'ERR';
?>

public function delete( $path, $version = -1 ) {}
<?php
$zookeeper = new Zookeeper('locahost:2181');
$path = '/path/to/node';
$r = $zookeeper->delete($path);
if ($r)
  echo 'SUCCESS';
else
  echo 'ERR';
?>

public function set( $path, $data, $version = -1, &$stat = null ) {}
<?php
$zookeeper = new Zookeeper('locahost:2181');
$path = '/path/to/node';
$value = 'nodevalue';
$r = $zookeeper->set($path, $value);
if ($r)
  echo 'SUCCESS';
else
  echo 'ERR';
?>

public function get( $path, $watcher_cb = null, &$stat = null, $max_size = 0) {}
<?php
$zookeeper = new Zookeeper('locahost:2181');
$path = '/path/to/node';
$value = 'nodevalue';
$zookeeper->set($path, $value);

$r = $zookeeper->get($path);
if ($r)
  echo $r;
else
  echo 'ERR';
?>

public function getChildren( $path, $watcher_cb = null ) {}
<?php
$zookeeper = new Zookeeper('locahost:2181');
$path = '/zookeeper';
$r = $zookeeper->getchildren($path);
if ($r)
  var_dump($r);
else
  echo 'ERR';
?>

public function exists( $path, $watcher_cb = null ) {}
<?php
$zookeeper = new Zookeeper('locahost:2181');
$path = '/path/to/node';
$r = $zookeeper->exists($path);
if ($r)
  echo 'EXISTS';
else
  echo 'N/A or ERR';
?>

注意:以上代码均来自php官网,大家可以执行一遍就会发现不少warning报错,主要集中在节点不存在时候的创建、查询、删除,不能直接创建删除子节点等问题,稍后会有针对说明和解决方案。

其中需要注意:

1 其中exists和get都可以设置$watcher_cb,该参数将会传入一个对象方法或者一个可调用函数,exists 会对zk下node的create,change,delete事件监听,而get不会监听create事件

2 create 只能创建一次,第二次创建将会报错(有部分开发者利用该特性来实现分布式锁,下一篇将会提到分布式锁的多实现方案)

3 set 和delete只能删除子节点,zk扩展本身不支持循环删除,也是上面出现的问题之一,这个需要我们自己实现,这里提供一个set的实现也是来自扩展官方的例子

<?php

class Zookeeper_Example
{

	public function __construct($address) {
		$this->zookeeper = new Zookeeper($address);
	}
	
	public function set($path, $value) {
		if (!$this->zookeeper->exists($path)) {
			$this->makePath($path);
			$this->makeNode($path, $value);
		} else {
			$this->zookeeper->set($path, $value);
		}
	}
	
	public function makePath($path, $value = '') {
		$parts = explode('/', $path);
		$parts = array_filter($parts);
		$subpath = '';
		while (count($parts) > 1) {
			$subpath .= '/' . array_shift($parts);
			if (!$this->zookeeper->exists($subpath)) {
				$this->makeNode($subpath, $value);
			}
		}
	}
	
	public function makeNode($path, $value, array $params = array()) {
		if (empty($params)) {
			$params = array(
				array(
					'perms'  => Zookeeper::PERM_ALL,
					'scheme' => 'world',
					'id'     => 'anyone',
				)
			);
		}
		return $this->zookeeper->create($path, $value, $params);
    }
    
    public function get($path) {
		if (!$this->zookeeper->exists($path)) {
			return null;
		}
		return $this->zookeeper->get($path);
	}
}
$zk = new Zookeeper_Example('localhost:2181');
var_dump($zk->set('/chenjie/info', 'bar1'));
var_dump($zk->get('/chenjie/info'));

 

这里采用的是对象的方式对zk默认方法封装更方便使用,点击查看扩展官方完整实例

https://github.com/andreiz/php-zookeeper/blob/master/examples/Zookeeper_Example.php

4 对于之前php官网中出现对不存在节点的创建、查询、删除报错的问题,建议先对节点进行exists判断,根据判断结果进行操作,避免warning报错影响业务流程