一、ZooKeeper应用实例详解

ZooKeeper是一个用于分布式应用的协同工作系统,确保数据的最新性、即时通知、顺序处理和一致性。本文通过UDC项目中的ZookeeperCacheSynchronizer类,详细解释了如何建立连接、注册和处理节点数据变化,以及实现缓存同步。
摘要由CSDN通过智能技术生成

 

ZooKeeper--动物园管理员,哈哈,管大象(Hadoop)、小猪(Pig)、蜂房Hive)等的管理员。

ZooKeeper是一个协同工作(或称协作支持)系统,分布式应用可以使用ZooKeeper来存储和协调关键共享状态。

ZooKeeper保证用户读取的数据是最新的;当用户正在查看的数据被修改时,保证用户会被即时通知;保证来自一个用户的所有请求会被按顺序处理;保证所有用户得到的数据是一致的。

 

下面这个例子是在UDC(会员数据中心,即诺亚方舟项目)项目中真实代码,此时为说明的清楚些,添加了大量的注释。

/**

 * @author zirou

 * 注意ZooKeeper的Watcher由读操作(exists/getData/getChildren)来注册,由写操作(create/delete/setData)来触发。

 */

@Component("zookeeperCacheSynchronizer")

public class ZookeeperCacheSynchronizer implements Watcher,CacheSynchronizer {

 

    private static finalLogger logger = LoggerFactory.getLogger(ZookeeperCacheSynchronizer.class);

    private static finalString HOSTS_KEy = "cache.zookeeper.hosts";

    private static finalString SESSION_TIMEOUT_KEy = "cache.zookeeper.sessionTimeout";

 

    private volatile booleanconnected = false;

    protected ZooKeeper zookeeper;

    private Map<String,CacheReader> readers = new ConcurrentHashMap<String, CacheReader>();

    private CountDownLatchconnectedSignal;

 

    @Resource

    private Map<String,String> configProperties;

    private String hosts;

    private intsessionTimeout;

 

    /**

     * 初始化,建立连接

     * @throwsKeeperException

     * @throwsInterruptedException

     */

    @PostConstruct

    public void initialize()throws KeeperException, InterruptedException {

        hosts =configProperties.get(HOSTS_KEy);

        sessionTimeout =Integer.valueOf(configProperties.get(SESSION_TIMEOUT_KEy));

 

        if (!connected) {

            connect();

        }

    }

 

    /**

     *建立连接:实例化一个新的ZooKeeper对象,且维护着客户端与ZooKeeper服务的链接。

     * @throwsKeeperException

     * @throwsInterruptedException

     */

 

    public synchronized voidconnect() {

       logger.info("ZookeeperCacheSynchronizer:connect");

        if (!connected) {

            try {

               connectedSignal = new CountDownLatch(1);

 

                //ZooKeeper构造函数有三个参数:1.是ZooKeeper服务的主机地址包括端口2.是会话超时时长

                //3.是Watcher对象的实例。Watcher对象接受ZooKeeper的响应,并通知它各种事件。

                // ZooKeeper客户端正是通过注册Watcher的方法来获取状态变化的信息。

                zookeeper =new ZooKeeper(hosts, sessionTimeout, new DefaultWatcher());




                //在使用zookeeper对象前,等待连接建立。这里利用Java的CountDownLatch类//(java.util.concurrent.CountDownLatch)来阻塞,直到zookeeper实例准备好。

               connectedSignal.await();

                connected =true;

               connectedSignal = null;

            } catch(Exception e) {

                throw newRuntimeException(e);

            }

        }

    }

 

    public void ensurePathExists(finalString path) {

        try {

            if (!connected){

                connect();

            }

 

            Stat stat =zookeeper.exists(path, false);

            if (stat !=null) {

                return;

            }

            zookeeper.create(path,new byte[]{1}, Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);

        } catch(KeeperException e) {

            throw newRuntimeException(e);

        } catch(InterruptedException e) {

            throw newRuntimeException(e);

        }

 

    }

 

    /**

     *客户端连接到ZooKeeper服务之后,Watcher的process方法会被调用,并收到一个事件。

     *

     * 

     */

    @Override

    public voidprocess(WatchedEvent event) {

       logger.info("ZookeeperCacheSynchronizer:process, path:" +event.getPath());




       //如果客户端收到的事件类型是NodeDataChanged,即被通知znode有改变,此时客户端就可执行具体的业务操作了。 

        if (event.getType()== EventType.NodeDataChanged) {

            try {

                byte[] b =zookeeper.getData(event.getPath(), this, null/* stat */);

                if(this.readers != null && this.readers.containsKey(event.getPath())) {

                   readers.get(event.getPath()).onRead(b);

                   logger.info("reader was found, path:" + event.getPath());

                } else {

                   logger.info("no reader found, path:" + event.getPath());

                }

            } catch(Exception e) {

                throw newRuntimeException(e);

            }

        }

    }

 

    @Override

    public voidregister(String path, CacheReader cachedReader) {

        try {

           ensurePathExists(path);

          //注册watcher

           zookeeper.getData(path, this, null/*stat*/);

        } catch (Exceptione) {

            throw newRuntimeException(e);

        }

        readers.put(path,cachedReader);

    }

 

    @Override

    public voidsyncReloadCache(String path, byte[] data) {

       logger.info("ZookeeperCacheSynchronizer:writeToZook
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值