Zookeeper提供类似shell环境,方便用户访问、操作数据,使用 bin目录下的 zkCli.sh命令,可以进入shell环境,同时可以查看到Zookeeper环境配置。
zkCli.sh [-server ip:port] | ./zkCli.sh -timeout 0 -r -server ip:port ./zkCli.sh -timeout 5000 -server 192.9.200.242:2181 -r :即使ZooKeeper服务器集群一般以上的服务器当掉,也给客户端体统读服务 |
h | 显示所有命令 |
ls path | 查看某个节点下的所有子节点信息 ls / :列出根节点下所有的子节点信息 ls2 path :是ls 和 stat两个命令的结合 |
create [-s] [-e] path dataacl | 创建节点 zk的节点分为两种:临时节点(随着zk session消亡而自动删除)、持久节点(一直存在) |
delete path [version] | 删除指定路径的节点如果有子节点要先删除子节点 |
rmr path | 递归删除一个znode,删除当前路径节点及其所有子节点 |
get path | 获取当前节点的数据内容 |
set path data [version] | 修改当前节点的数据内容 如果指定版本,需要和当前节点的数据版本一致 |
connect host:port / clost | 连接到指定节点 / 关闭服务器 |
history / redo cmdno | 查看客户端这次会话所执行的所有命令 / 执行指定历史命令 |
setquota -n|-b val path | 某个Znode指定多少存储空间或者允许创建多少个节点 n 指定可以设置多少个子节点 b 指定可以设置多大空间(byte) 对于配额不是硬性的提示,超过配额还是可以继续创建,只不过在日志里面有提示 (遇到问题记得看 zeekeeper.out 这个文件 ,默认在zk的bin目录下, 命令:tail –f zookeeper.out) |
listquotapath | 查看配额信息 |
delquota [-n|-b] path | 删除节点路径的配额信息 |
stat path | 查看节点的状态 czxid 创建该节点的事物ID |
quit | 退出客户端 |
/**
* 该类解释怎么去连接zk并监听事件
* psvm --- main
* sout --- syso
*
*/
public class ZKDemo{
public static void main(String[] args) throws IOException {
ZooKeeper zk = new ZooKeeper("192.168.121.99:22", 5000, new MyWatcher());
System.out.println("zkState --- >"+zk.getState());
}
}
/**
* 监听器
*/
class MyWatcher implements Watcher{
public void process(WatchedEvent event) {
System.out.println("Receive watched event:" + event);
}
}
/**
解释如何去创建znode并监听事件
*/
public class ZKOperateDemo implements Watcher {
private static final CountDownLatch cdl = new CountDownLatch(1);
public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
ZooKeeper zk = new ZooKeeper("192.168.56.101:2181", 5000, new ZKOperateDemo());
cdl.await();
String path1 = zk.create("/zk-test-", "123".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
System.out.println("Success create path: " + path1);
String path2 = zk.create("/zk-test-", "456".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
System.out.println("Success create path: " + path2);
}
@Override
public void process(WatchedEvent event) {
System.out.println("Receive watched event:" + event);
if (KeeperState.SyncConnected == event.getState()) {
cdl.countDown();
}
}
}
/**
解释如何改变znode数据并监听事件
*/
public class ZKDataDemo implements Watcher {
private static final CountDownLatch cdl = new CountDownLatch(1);
private static ZooKeeper zk = null;
private static Stat stat = new Stat();
public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
zk = new ZooKeeper("192.168.56.101:2181", 5000, new ZKDataDemo());
cdl.await();
zk.create("/zk-test", "123".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
System.out.println(new String(zk.getData("/zk-test", true, stat)));
zk.getData("/zk-test", true, stat);
System.out.println(stat.getCzxid() + ", " + stat.getMzxid() + ", " + stat.getVersion());
zk.setData("/zk-test", "123".getBytes(), -1);
Thread.sleep(Integer.MAX_VALUE);
}
@Override
public void process(WatchedEvent event) {
if (KeeperState.SyncConnected == event.getState()) {
if (EventType.None == event.getType() && null == event.getPath()) {
cdl.countDown();
} else if (event.getType() == EventType.NodeDataChanged) {
try {
System.out.println(new String(zk.getData(event.getPath(), true, stat)));
System.out.println(stat.getCzxid() + ", " + stat.getMzxid() + ", " + stat.getVersion());
} catch (Exception e) {
}
}
}
}
}
/**
解释如何改变子节点并监听事件
*/
public class ZKChildrenDemo implements Watcher {
private static final CountDownLatch cdl = new CountDownLatch(1);
private static ZooKeeper zk = null;
public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
zk = new ZooKeeper("192.168.56.101:2181", 5000, new ZKChildrenDemo());
cdl.await();
zk.create("/zk-test", "123".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
zk.create("/zk-test/c1", "456".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
List list = zk.getChildren("/zk-test", true);
for (String str : list)
System.out.println(str);
zk.create("/zk-test/c2", "789".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
Thread.sleep(Integer.MAX_VALUE);
}
@Override
public void process(WatchedEvent event) {
if (KeeperState.SyncConnected == event.getState())
if (EventType.None == event.getType() && null == event.getPath()) {
cdl.countDown();
} else if (event.getType() == EventType.NodeChildrenChanged) {
try {
System.out.println("Child: " + zk.getChildren(event.getPath(), true));
} catch (Exception e) {
}
}
}
}
/**
解释如何异步调用并完成回调
*/
class ChildrenCallback implements AsyncCallback.Children2Callback {
@Override
public void processResult(int rc, String path, Object ctx, List children, Stat stat) {
System.out.println(
"Child: " + rc + ", path: " + path + ", ctx: " + ctx + ", children: " + children + ", stat: " + stat);
}
}
public class ZKChildrenAsyncDemo implements Watcher {
private static final CountDownLatch cdl = new CountDownLatch(1);
private static ZooKeeper zk = null;
public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
zk = new ZooKeeper("192.168.56.101:2181", 5000, new ZKChildrenAsyncDemo());
cdl.await();
zk.create("/zk-test", "123".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
zk.create("/zk-test/c1", "456".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
zk.getChildren("/zk-test", true, new ChildrenCallback(), "ok");
Thread.sleep(Integer.MAX_VALUE);
}
@Override
public void process(WatchedEvent event) {
if (KeeperState.SyncConnected == event.getState())
if (EventType.None == event.getType() && null == event.getPath()) {
cdl.countDown();
} else if (event.getType() == EventType.NodeChildrenChanged) {
try {
System.out.println("Child: " + zk.getChildren(event.getPath(), true));
} catch (Exception e) {
}
}
}
}
ACID,指数据库事务正确执行的四个基本要素的缩写。包含:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。
事务里的每一个步骤都必须完成,否则只能都不完成。不能只执行一部分事务。
事务完成后应该维持数据库的一致性。
表示每次事务都会看到具有一致性的数据库,无论其他事务有什么行动。
在事务完成以后,该事务对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。
2P- 阶段1:提交事务请求(投票阶段)
2P- 阶段2:执行事务提交(commit、rollback)
3P- 阶段1:是否提交
3P- 阶段2:预先提交
3P- 阶段3:提交(commit、rollback)
与2PC区别:
>第二阶段才写undo和redo事务日志>参与者也会commit
优点:
> 改善同步阻塞
> 改善单点故障
缺点:
> 同步阻塞
> 单点故障
> 数据不一致
> 容错机制不完善
CAP: 一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)
CAP理论: 一个分布式系统不可能同时满足一致性、可用性和分区容错性这三个基本需求,最多只能同时满足其中的两项;
数据在分布式环境下的多个副本之间能否保持一致性,这里
的一致性更多是指强一致性;
分布式系统一直处于可用状态,对于请求总是能在有限的时间
内返回结果致性;
除非整个网络故障,分布式系统在任何网络或者单点故障
时,仍能对外提供满足一致性和可用性的服务;
序号 | 组合 | 说明 |
1 | 放弃P,满足AC | 将数据和服务都放在一个节点上,避免因网络引起的负面 影响,充分保证系统的可用性和一致性。但放弃P意味着 放弃了系统的可扩展性 |
2 | 放弃A,满足PC | 当节点故障或者网络故障时,受到影响的服务需要等待一 定的世界,因此在等待时间里,系统无法对外提供正常服 务,因此是不可用的; |
3 | 放弃C,满足AP | 系统无法保证数据的实时一致性,但是承诺数据最终会保 证一致性。因此存在数据不一致的窗口期,至于窗口期的 长短取决于系统的设计 |
BASE:基本可用(Bascially Available)、软状态(Soft state)、最终一致性(Eventually consistent)
BASE理论:即使无法做到强一致性,但分布式系统可以根据自己的业务特点,采用适当的方式来使系统达到最终的一致性;
当分布式系统出现不可预见的故障时,允许损失部分可用性,保障系统的“基本可用”;体现在“时间上的损失”和“功能上的损失”;e.g:部分用户双十一高峰期淘宝页面卡顿或降级处理;
允许系统中的数据存在中间状态,既系统的不同节点的数据副本之间的数据同步过程存在延时,并认为这种延时不会影响系统可用性;e.g:12306网站卖火车票,请求会进入排队队列;
所有的数据在经过一段时间的数据同步后,最终能够达到一个一致的状态;e.g:理财产品首页充值总金额短时不一致;