(八)、ZooKeeper 事物

利用Transaction提交创建节点

代码如下:
/**
     * <p>创建zNode节点, String create(path<节点路径>, data[]<节点内容>, List(ACL访问控制列表), CreateMode<zNode创建类型>) </p><br/>
     * <pre>
     *     节点创建类型(CreateMode)
     *     1、PERSISTENT:持久化节点
     *     2、PERSISTENT_SEQUENTIAL:顺序自动编号持久化节点,这种节点会根据当前已存在的节点数自动加 1
     *     3、EPHEMERAL:临时节点客户端,session超时这类节点就会被自动删除
     *     4、EPHEMERAL_SEQUENTIAL:临时自动编号节点
     * </pre>
     * @param path zNode节点路径
     * @param data zNode数据内容
     * @return 创建成功返回true, 反之返回false.
     */
	public boolean createZNode(String path,String data){
		try {
			String zkPath = MyZooKeeper.zooKeeper.create(path, data.getBytes(),
					acls, CreateMode.PERSISTENT);
			logger.info("ZooKeeper创建节点成功,节点地址:" + zkPath);
			return true;
		} catch (KeeperException e) {
			logger.error("创建节点失败:" + e.getMessage() + ",path:" + path  ,e);
		} catch (InterruptedException e) {
			logger.error("创建节点失败:" + e.getMessage() + ",path:" + path  ,e);
		}
		return false;
	}
批量创建多个时,可以引入事物来进行对创建的控制:
public boolean createZNode(List<String> path,List<String> data){
		try {
			Transaction tx = MyZooKeeper.zooKeeper.transaction();
			for (int i = 0,len = path.size(); i < len; i++) {
				createZNode(path.get(i), data.get(i));
			}
			tx.commit();
			return true;
		} catch (InterruptedException e) {
			logger.error("创建节点失败:" + e.getMessage() + ",path:" + path  ,e);
		} catch (KeeperException e) {
			logger.error("创建节点失败:" + e.getMessage() + ",path:" + path  ,e);
		}
		return false;
	}

Zookeeper对于事务性的支持 

       它对于事务性的支持主要依赖于四个函数支持主要依赖于四个函数,zoo_create_op_initzoo_delete_op_initzoo_set_op_init以及zoo_check_op_init。每一个函数都会在客户端初始化一个operation,客户端程序有义务保留这些operations。当准备好一个事务中的所有操作后,可以使用zoo_multi来提交所有的操作,由zookeeper服务来保证这一系列操作的原子性。也就是说只要其中有一个操作失败了,相当于此次提交的任何一个操作都没有对服务端的数据造成影响。Zoo_multi的返回值是第一个失败操作的状态信号。

        Zookeeper通过版本号来保证操作的实效性。zoo_set的最后一个形参就是version number。如果提交的数和服务端在该节点的版本号对不上,那么此次设值操作就失败了。这可以解决这样的情况:client1.get, client2.get, client2.set, client1.set。从client1的角度出发,set和get之前操作的变量值已经发生改变了,zookeeper非常负责的保证的最后一次set将不会成功,客户端可以重新get, set一次。

Zookeeper查看事物日志

zookeeper的事务日志通过zoo.cfg文件中的dataLogDir配置项配置,文件如下:


zookeeper提供了查看事务日志的工具类LogFormatter ,运行:

java -classpath .:slf4j-api-1.6.1.jar:zookeeper-3.4.5.jar org.apache.zookeeper.server.LogFormatter /export1/zookeeper/logs/version-2/log.1000003d2 

将看到格式化的日志内容类似:
    ZooKeeper Transactional Log File with dbid 0 txnlog format version 2  
    5/12/14 7:06:31 PM CST session 0x145ef610b530000 cxid 0x229e zxid 0x1000003e8 delete '/hbase/region-in-transition/e3d18e83988febe321e563f085210127  
    5/12/14 7:06:31 PM CST session 0x245ef610b52004c cxid 0x0 zxid 0x1000003e9 createSession 40000  
    5/12/14 7:06:31 PM CST session 0x245ef610b52004c cxid 0x3 zxid 0x1000003ea closeSession null  
    5/12/14 7:06:31 PM CST session 0x545f01346c60001 cxid 0x0 zxid 0x1000003eb createSession 40000  
    5/12/14 7:06:31 PM CST session 0x545f01346c60001 cxid 0x3 zxid 0x1000003ec closeSession null  
    5/12/14 7:06:32 PM CST session 0x445f018d5e00002 cxid 0x0 zxid 0x1000003ed createSession 40000  
    5/12/14 7:06:32 PM CST session 0x445f018d5e00002 cxid 0x3 zxid 0x1000003ee closeSession null  
    5/12/14 7:06:32 PM CST session 0x145ef610b530000 cxid 0x22a1 zxid 0x1000003ef setData '/hbase/table/wyp,#ffffffff000146d61737465723a36303030303b36ffffffc765ffffffb0ffffffa5ffffffa3745042554681,5  
    5/12/14 7:06:32 PM CST session 0x145ef610b530000 cxid 0x22a3 zxid 0x1000003f0 delete '/hbase/table-lock/wyp/write-master:600000000000002  
    5/12/14 7:06:32 PM CST session 0x145ef610b530033 cxid 0x0 zxid 0x1000003f1 createSession 40000  
    5/12/14 7:06:32 PM CST session 0x145ef610b530033 cxid 0x3 zxid 0x1000003f2 closeSession null  
LogFormatter 类代码如下:
/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.zookeeper.server;

import java.io.ByteArrayInputStream;
import java.io.EOFException;
import java.io.FileInputStream;
import java.io.IOException;
import java.text.DateFormat;
import java.util.Date;
import java.util.zip.Adler32;
import java.util.zip.Checksum;

import org.apache.jute.BinaryInputArchive;
import org.apache.jute.InputArchive;
import org.apache.jute.Record;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.zookeeper.server.persistence.FileHeader;
import org.apache.zookeeper.server.persistence.FileTxnLog;
import org.apache.zookeeper.server.util.SerializeUtils;
import org.apache.zookeeper.txn.TxnHeader;

public class LogFormatter {
    private static final Logger LOG = LoggerFactory.getLogger(LogFormatter.class);

    /**
     * @param args
     */
    public static void main(String[] args) throws Exception {
        if (args.length != 1) {
            System.err.println("USAGE: LogFormatter log_file");
            System.exit(2);
        }
        FileInputStream fis = new FileInputStream(args[0]);
        BinaryInputArchive logStream = BinaryInputArchive.getArchive(fis);
        FileHeader fhdr = new FileHeader();
        fhdr.deserialize(logStream, "fileheader");

        if (fhdr.getMagic() != FileTxnLog.TXNLOG_MAGIC) {
            System.err.println("Invalid magic number for " + args[0]);
            System.exit(2);
        }
        System.out.println("ZooKeeper Transactional Log File with dbid "
                + fhdr.getDbid() + " txnlog format version "
                + fhdr.getVersion());

        int count = 0;
        while (true) {
            long crcValue;
            byte[] bytes;
            try {
                crcValue = logStream.readLong("crcvalue");

                bytes = logStream.readBuffer("txnEntry");
            } catch (EOFException e) {
                System.out.println("EOF reached after " + count + " txns.");
                return;
            }
            if (bytes.length == 0) {
                // Since we preallocate, we define EOF to be an
                // empty transaction
                System.out.println("EOF reached after " + count + " txns.");
                return;
            }
            Checksum crc = new Adler32();
            crc.update(bytes, 0, bytes.length);
            if (crcValue != crc.getValue()) {
                throw new IOException("CRC doesn't match " + crcValue +
                        " vs " + crc.getValue());
            }
            TxnHeader hdr = new TxnHeader();
            Record txn = SerializeUtils.deserializeTxn(bytes, hdr);
            System.out.println(DateFormat.getDateTimeInstance(DateFormat.SHORT,
                    DateFormat.LONG).format(new Date(hdr.getTime()))
                    + " session 0x"
                    + Long.toHexString(hdr.getClientId())
                    + " cxid 0x"
                    + Long.toHexString(hdr.getCxid())
                    + " zxid 0x"
                    + Long.toHexString(hdr.getZxid())
                    + " " + TraceFormatter.op2String(hdr.getType()) + " " + txn);
            if (logStream.readByte("EOR") != 'B') {
                LOG.error("Last transaction was partial.");
                throw new EOFException("Last transaction was partial.");
            }
            count++;
        }
    }
}



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值