读《分布式一致性原理》java客户端api操作3 -ag凯发k8国际
更新数据
客户端可以通过zookeeper的api来更新一个节点的数据内容,有如下两个接口:
public stat setdata(final string path, byte data[], int version)public void setdata(final string path, byte data[], int version,statcallback cb, object ctx)
更新数据的接口较为简单明了。我们重点来看下方法中的version参数。version参数是指定节点的数据版本。表明本次更新是针对指定版本进行的。
《java并发编程实践》一书提到,在现代的绝大数计算机处理器体系架构中,都实现了对cas指令支持,
通俗的将,cas的意思是“对于值v,每次更新都会对其值是否是值是否是预期值a,只有符合预期,才会将a原子化的更新为b”。zookeeper中setdata接口中的version参数正是由cas原理演化而来的。
具体来说,假如有个客户端想要进行更新操作,那么肯定会携带上次获取的version值进行更新。如果在这段时间,该数据恰好被其他客户端更新了,那么其数据版本一定也发生了变化,因此肯定与客户端携带的version无法匹配,于是便无法更新成功。可以有效的避免分布式更新的并发问题。
使用同步api更新节点数据内容
package setdata;import java.io.ioexception; import java.util.concurrent.countdownlatch;import org.apache.zookeeper.createmode; import org.apache.zookeeper.keeperexception; import org.apache.zookeeper.watchedevent; import org.apache.zookeeper.watcher; import org.apache.zookeeper.zookeeper; import org.apache.zookeeper.watcher.event.eventtype; import org.apache.zookeeper.watcher.event.keeperstate; import org.apache.zookeeper.zoodefs.ids; import org.apache.zookeeper.data.stat;import getdata.getdata1;public class setdata1 implements watcher {public static countdownlatch connectedsemaphore = new countdownlatch(1);private static zookeeper zk = null;private static stat stat = new stat();@overridepublic void process(watchedevent event) {if (keeperstate.syncconnected==event.getstate()) {if (eventtype.none.getintvalue()==event.getstate().getintvalue()&&null==event.getpath()) {connectedsemaphore.countdown();}}}public static void main(string[] args) throws ioexception, interruptedexception, keeperexception {string path = "/zk-book";zk = new zookeeper("192.168.64.60:2181", 5000, new setdata1());connectedsemaphore.await();zk.create(path, "123".getbytes(), ids.open_acl_unsafe, createmode.ephemeral);stat stat2 = zk.setdata(path, "456".getbytes(), -1);system.out.println(stat.getczxid() "---" stat.getmzxid() "--" stat.getversion());thread.sleep(integer.max_value);;}}
在zookeeper中,数据版本都是从0开始的,所以严格来讲-1并不是一个数据版本,它仅仅是一个
标示符,是告诉服务器对最新版本进行更新操作。如果对zookeeper数据节点的更新操作没有原子性要求,那么就可以使用“-1”;
所以用异步的api更新数据内容
package getdata;import java.io.ioexception; import java.util.concurrent.countdownlatch;import org.apache.zookeeper.asynccallback; import org.apache.zookeeper.createmode; import org.apache.zookeeper.keeperexception; import org.apache.zookeeper.watchedevent; import org.apache.zookeeper.watcher; import org.apache.zookeeper.zookeeper; import org.apache.zookeeper.data.stat; import org.apache.zookeeper.watcher.event.eventtype; import org.apache.zookeeper.watcher.event.keeperstate; import org.apache.zookeeper.zoodefs.ids;public class getdata2 implements watcher {public static countdownlatch connectedsemaphore = new countdownlatch(1);private static zookeeper zk = null;private static stat stat = new stat();@overridepublic void process(watchedevent event) {if (keeperstate.syncconnected==event.getstate()) {if (eventtype.none.getintvalue()==event.getstate().getintvalue()&&null==event.getpath()) {connectedsemaphore.countdown();}}}public static void main(string[] args) throws ioexception, interruptedexception, keeperexception {string path = "/zk-book";zk = new zookeeper("192.168.64.60:2181", 5000, new getdata2());connectedsemaphore.await();zk.create(path, "123".getbytes(), ids.open_acl_unsafe, createmode.ephemeral );zk.setdata(path, "456".getbytes(), -1,new idataback(),"");thread.sleep(integer.max_value);;} }class idataback implements asynccallback.statcallback{@overridepublic void processresult(int rc, string path, object ctx, stat stat) {if (rc==0) {system.out.println("success");}}}
检测节点是否存在
客户端可以通过zookeeper的api来检测一个节点
该接口主要用于检测指定节点是否存在,返回值是一个stat对象。如果在调用接口时注册watcher的话,
还可以对节点是否存在进行监听,一旦节点被创建被删除或被更新,都会通知客户端。
权限控制
在zookeeper的实际使用中,我们的做法往往是搭建一个共用的zookeeper集群,同一为若干个应用提供服务,在这种情况下,不同的应用往往是不存在共享数据的场景的。因此需要解决不同应用之间的权限问题。
zookeeper提供了多种权限控制模式(scheme),分别是world,auth,digest,ip和super。
本节中我们主要讲digest模式下是如何进行zookeeper权限控制的。
开发人员如果要使用zookeeper的权限控制功能,需要在zookeeper完成会话创建的时候,给该会话添加相关的权限信息(authinfo)。zookeeper客户端提供了相应的api接口来进行权限信息的设置。
该接口的主要作用是为当前的zookeeper会话添加权限信息,之后范式通过该会话对zookeeper服务端进行的任何操作都会带上该权限信息。
使用包含权限信息的zookeeper会话创建数据节点。
package auth;import java.io.ioexception; import org.apache.zookeeper.createmode; import org.apache.zookeeper.keeperexception; import org.apache.zookeeper.zoodefs.ids; import org.apache.zookeeper.zookeeper;public class authinfo {final static string path="/zk-book-auth_test";public static void main(string[] args) throws ioexception, keeperexception, interruptedexception {zookeeper zk = new zookeeper("192.168.64.60:2181", 5000, null);zk.addauthinfo("digest", "foo:true".getbytes());zk.create(path, "123".getbytes(), ids.creator_all_acl, createmode.ephemeral);thread.sleep(integer.max_value);} }
使用无权限信息的zookeeper会话访问权限信息的数据节点。
package auth;import java.io.ioexception; import org.apache.zookeeper.createmode; import org.apache.zookeeper.keeperexception; import org.apache.zookeeper.zoodefs.ids; import org.apache.zookeeper.zookeeper;public class authinfo2 {final static string path="/zk-book-auth_test";public static void main(string[] args) throws ioexception, keeperexception, interruptedexception {zookeeper zk = new zookeeper("192.168.64.60:2181", 5000, null);zk.addauthinfo("digest", "foo:true".getbytes());zk.create(path, "123".getbytes(), ids.creator_all_acl, createmode.ephemeral);zookeeper zk2 = new zookeeper("192.168.64.60:2181", 5000, null);zk2.getdata(path, false, null);thread.sleep(integer.max_value);} }
一旦我们对一个数据节点设置了权限信息,那么其他没有权限设置的客户端会话将无法访问该数据节点。
对于删除及诶单(delete)接口而言,其权限控制比较特殊。
import org.apache.zookeeper.createmode; import org.apache.zookeeper.zoodefs.ids; import org.apache.zookeeper.zookeeper; /** * * @classname: authsample_delete * @description: todo(删除节点的权限控制) * @author rongshu * @date 2017年6月11日 下午8:41:23 * */ public class authsample_delete { final static string path = "/zk-book-auth_test"; final static string path2 = "/zk-book-auth_test/child"; public static void main(string[] args) throws exception { zookeeper zookeeper1 = new zookeeper("localhost:2181",5000,null); zookeeper1.addauthinfo("digest", "foo:true".getbytes()); zookeeper1.create( path, "init".getbytes(), ids.creator_all_acl, createmode.persistent ); zookeeper1.create( path2, "init".getbytes(), ids.creator_all_acl, createmode.ephemeral ); try { zookeeper zookeeper2 = new zookeeper("localhost:2181",50000,null); zookeeper2.delete( path2, -1 ); } catch ( exception e ) { system.out.println( "删除节点失败: " e.getmessage() ); } zookeeper zookeeper3 = new zookeeper("localhost:2181",50000,null); zookeeper3.addauthinfo("digest", "foo:true".getbytes()); zookeeper3.delete( path2, -1 ); system.out.println( "成功删除节点:" path2 ); zookeeper zookeeper4 = new zookeeper("localhost:2181",50000,null); zookeeper4.delete( path, -1 ); system.out.println( "成功删除节点:" path ); } } 输出 删除节点失败: keepererrorcode = noauth for /zk-book-auth_test/child 成功删除节点:/zk-book-auth_test/child 成功删除节点:/zk-book-auth_test注意:
当客户端对一个数据节点添加了权限信息后,对于删除操作而言,其作用范围是其子节点,也就是说,当我们对一个数据节点添加权限信息之后,依然可以自由的删除这个节点,但是对于这个节点的子节点,就必须使用相应的权限信息才能够删掉它。
转载于:https://www.cnblogs.com/duan2/p/9070011.html
总结
以上是ag凯发k8国际为你收集整理的读《分布式一致性原理》java客户端api操作3的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇:
- 下一篇: