Zookeeper 异常讲解,减少踩坑「终于解决」

Zookeeper 异常讲解,减少踩坑「终于解决」Zookeeper异常在Zookeeper的JavaAPI中每一个连接操作zk的时候【create、delete、getChildren等】都抛

大家好,欢迎来到IT知识分享网。

Zookeeper 异常讲解,减少踩坑「终于解决」

Zookeeper异常

在Zookeeper的Java API中每一个连接操作zk的时候【create、delete、getChildren等】都抛出了两个异常,一是InterruptedException,一是KeeperException,如以下代码:

public List<String> getChildrenNodes(String parentPath)
	{
		List<String> nodeList = new ArrayList<String>();
		try 
		{
			nodeList = this.zkClient.zookeeper.getChildren(parentPath, null);
		} 
		catch (KeeperException e) 
		{
			e.printStackTrace();
		} 
		catch (InterruptedException e) 
		{
			e.printStackTrace();
		}
		return nodeList;
	}

IT知识分享网

1、InterruptedException异常

Zookeeper通过InterruptedException来终止一个阻塞的zookeeper操作,因此,出此异常并不意味着就有故障,反而可以说相应的操作被取消,类似线程的Interrupt

2、KeeperException异常

如果服务器出错或者客户端与服务器存在通信方面的问题,此时就会抛出该异常,

  • 如试图对一个不存在的zk节点进行一些操作,则会抛出KeeperException.NoNodeException,NoNodeException是KeeperException的子类;
  • 当新建一个zookeeper实例的时候,如果实例状态还没有切换到Connected状态就去进行一些zk操作,此时可能抛出KeeperException.ConnectionLossException;
  • 而试图在短暂znode下创建子节点时就会抛出KeeperException.NoChildrenForEphemeralsException异常
  • 又或者如果一个znode先被另外一个进程更新了,根据版本号执行setData操作的进程就会失败,并收到一个KeeperException.BadVersionException异常,这是因为版本号不匹配。程序员通常都知道这种冲突总是存在的,也都会编写代码来进行处理。

处理上面的异常,通常是捕获KeeperException然后判断子类型进行相应的补救操作,或者捕获对应的子异常再进行相应的操作。

一个可恢复的异常是通过KeeperException.ConnectionLossException来表示的,它意味着已经丢失了与ZooKeeper的连接。ZooKeeper会尝试重新连接,并且在大多数情况下重新连接会成功,并确保会话是完整的。但是zk不能判断与该异常相关的操作是否已经完成,那么我们就要对这种不确定的东西进行处理,此时就涉及“幂等操作”与“非幂等操作”。

幂等操作就是不管执行多少次,结果都是一样的,相反,非幂等操作一次操作与多次操作的结果是截然不同的。

Zookeeper 异常讲解,减少踩坑「终于解决」

如在分布式锁案例中,我们每个客户端都需要创建自己的锁节点,如下:

IT知识分享网public String createNode(String nodePath, CreateMode createMode)
	{
		String nodePathCreated = "";
		try 
		{
			nodePathCreated = this.zkClient.zookeeper.create(nodePath, null, ZooDefs.Ids.OPEN_ACL_UNSAFE, createMode);
		} 
		catch (KeeperException e) 
		{
			e.printStackTrace();
		} 
		catch (InterruptedException e) 
		{
			e.printStackTrace();
		}
		return nodePathCreated;
	}

上述代码没有处理因连接丢失而导致的create操作失败。如前所述,在这种情况下,我们不知道操作是成功还是失败。由于创建一个顺序znode是非幂等操作,所以我们不能简单地重试,因为如果第一次创建已经成功,重试就会多出一个孤儿节点,可能导致死锁。

那么分布式锁中我们如何解决这个问题好呢?

其实每一个zk会话都有一个session,sessionId可以通过getSessionld()方法获得,我们在建立锁节点的时候应该建为这样的格式【lock_sessionId_0000000100】,当zk再次连接上的时候再去重试时,我们需要判断zk上是否已经存在有与当前sessionId一致的节点,有就不再创建,否则再建,并监听比自己小的节点的删除事件。

好了,关于zookeeper更多的问题,大家有什么见解,欢迎再次留言评论,我们一起成长!

Zookeeper 异常讲解,减少踩坑「终于解决」



免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/13456.html

(0)
上一篇 2023-03-08 12:30
下一篇 2023-03-08 13:30

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

关注微信