欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

ZooKeeper 實(shí)現(xiàn)分布式鎖的方法示例

 更新時(shí)間:2019年06月17日 09:05:09   作者:Beck''s Blog  
這篇文章主要介紹了ZooKeeper 實(shí)現(xiàn)分布式鎖的方法示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

ZooKeeper 是一個(gè)典型的分布式數(shù)據(jù)一致性解決方案,分布式應(yīng)用程序可以基于 ZooKeeper 實(shí)現(xiàn)諸如數(shù)據(jù)發(fā)布/訂閱、負(fù)載均衡、分布式協(xié)調(diào)/通知、集群管理、Master 選舉、分布式鎖等功能。

節(jié)點(diǎn)

在介紹 ZooKeeper 分布式鎖前需要先了解一下 ZooKeeper 中節(jié)點(diǎn)(Znode),ZooKeeper 的數(shù)據(jù)存儲(chǔ)數(shù)據(jù)模型是一棵樹(shù)(Znode Tree),由斜杠(/)的進(jìn)行分割的路徑,就是一個(gè) Znode(如 /locks/my_lock)。每個(gè) Znode 上都會(huì)保存自己的數(shù)據(jù)內(nèi)容,同時(shí)還會(huì)保存一系列屬性信息。

Znode 又分為以下四種類型:

類型 描述
持久節(jié)點(diǎn) 節(jié)點(diǎn)創(chuàng)建后,會(huì)一直存在,不會(huì)因客戶端會(huì)話失效而刪除
持久順序節(jié)點(diǎn) 基本特性與持久節(jié)點(diǎn)一致,創(chuàng)建節(jié)點(diǎn)的過(guò)程中,ZooKeeper 會(huì)在其名字后自動(dòng)追加一個(gè)單調(diào)增長(zhǎng)的數(shù)字后綴,作為新的節(jié)點(diǎn)名
臨時(shí)節(jié)點(diǎn) 客戶端會(huì)話失效或連接關(guān)閉后,該節(jié)點(diǎn)會(huì)被自動(dòng)刪除
臨時(shí)順序節(jié)點(diǎn) 基本特性與臨時(shí)節(jié)點(diǎn)一致,創(chuàng)建節(jié)點(diǎn)的過(guò)程中,ZooKeeper 會(huì)在其名字后自動(dòng)追加一個(gè)單調(diào)增長(zhǎng)的數(shù)字后綴,作為新的節(jié)點(diǎn)名

鎖原理

ZooKeeper 分布式鎖是基于 臨時(shí)順序節(jié)點(diǎn) 來(lái)實(shí)現(xiàn)的,鎖可理解為 ZooKeeper 上的一個(gè)節(jié)點(diǎn),當(dāng)需要獲取鎖時(shí),就在這個(gè)鎖節(jié)點(diǎn)下創(chuàng)建一個(gè)臨時(shí)順序節(jié)點(diǎn)。當(dāng)存在多個(gè)客戶端同時(shí)來(lái)獲取鎖,就按順序依次創(chuàng)建多個(gè)臨時(shí)順序節(jié)點(diǎn),但只有排列序號(hào)是第一的那個(gè)節(jié)點(diǎn)能獲取鎖成功,其他節(jié)點(diǎn)則按順序分別監(jiān)聽(tīng)前一個(gè)節(jié)點(diǎn)的變化,當(dāng)被監(jiān)聽(tīng)者釋放鎖時(shí),監(jiān)聽(tīng)者就可以馬上獲得鎖。

而且用臨時(shí)順序節(jié)點(diǎn)的另外一個(gè)用意是如果某個(gè)客戶端創(chuàng)建臨時(shí)順序節(jié)點(diǎn)后,自己意外宕機(jī)了也沒(méi)關(guān)系,ZooKeeper 感知到某個(gè)客戶端宕機(jī)后會(huì)自動(dòng)刪除對(duì)應(yīng)的臨時(shí)順序節(jié)點(diǎn),相當(dāng)于自動(dòng)釋放鎖。

如上圖:ClientA 和 ClientB 同時(shí)想獲取鎖,所以都在 locks 節(jié)點(diǎn)下創(chuàng)建了一個(gè)臨時(shí)節(jié)點(diǎn) 1 和 2,而 1 是當(dāng)前 locks 節(jié)點(diǎn)下排列序號(hào)第一的節(jié)點(diǎn),所以 ClientA 獲取鎖成功,而 ClientB 處于等待狀態(tài),這時(shí) ZooKeeper 中的 2 節(jié)點(diǎn)會(huì)監(jiān)聽(tīng) 1 節(jié)點(diǎn),當(dāng) 1節(jié)點(diǎn)鎖釋放(節(jié)點(diǎn)被刪除)時(shí),2 就變成了 locks 節(jié)點(diǎn)下排列序號(hào)第一的節(jié)點(diǎn),這樣 ClientB 就獲取鎖成功了。

代碼測(cè)試

請(qǐng)確保 ZooKeeper 服務(wù)已啟動(dòng),ZooKeeper 的搭建可參考Kafka 集群 中的 ZooKeeper 集群部分

以下是基于 C# 的測(cè)試,Java 可使用 Curator 框架,實(shí)現(xiàn)原理和上面描述是一致的,有興趣可以看看源碼,應(yīng)該也不難理解。

創(chuàng)建 .NET Core 控制臺(tái)程序 Nuget

安裝 ZooKeeperNetEx.Recipes

創(chuàng)建 ZooKeeper Client

private const int CONNECTION_TIMEOUT = 50000;
private const string CONNECTION_STRING = "127.0.0.1:2181";
private ZooKeeper CreateClient()
{
	var zooKeeper = new ZooKeeper(CONNECTION_STRING, CONNECTION_TIMEOUT, NullWatcher.Instance);
	Stopwatch sw = new Stopwatch();
	sw.Start();
	while (sw.ElapsedMilliseconds < CONNECTION_TIMEOUT)
	{
		var state = zooKeeper.getState();
		if (state == ZooKeeper.States.CONNECTED || state == ZooKeeper.States.CONNECTING)
		{
			break;
		}
	}
	sw.Stop();
	return zooKeeper;
}

class NullWatcher : Watcher
  {
    public static readonly NullWatcher Instance = new NullWatcher();
    private NullWatcher() { }
    public override Task process(WatchedEvent @event)
    {
      return Task.CompletedTask;
    }
  }

添加 Lock 方法

/// <summary>
/// 加鎖
/// </summary>
/// <param name="key">加鎖的節(jié)點(diǎn)名</param>
/// <param name="lockAcquiredAction">加鎖成功后需要執(zhí)行的邏輯</param>
/// <param name="lockReleasedAction">鎖釋放后需要執(zhí)行的邏輯,可為空</param>
/// <returns></returns>
public async Task Lock(string key, Action lockAcquiredAction, Action lockReleasedAction = null)
{
	// 獲取 ZooKeeper Client
	ZooKeeper keeper = CreateClient();
	// 指定鎖節(jié)點(diǎn)
	WriteLock writeLock = new WriteLock(keeper, $"/{key}", null);

	var lockCallback = new LockCallback(() =>
	{
		lockAcquiredAction.Invoke();
		writeLock.unlock();
	}, lockReleasedAction);
	// 綁定鎖獲取和釋放的監(jiān)聽(tīng)對(duì)象
	writeLock.setLockListener(lockCallback);
	// 獲取鎖(獲取失敗時(shí)會(huì)監(jiān)聽(tīng)上一個(gè)臨時(shí)節(jié)點(diǎn))
	await writeLock.Lock();
}

class LockCallback : LockListener
{
	private readonly Action _lockAcquiredAction;
	private readonly Action _lockReleasedAction;

	public LockCallback(Action lockAcquiredAction, Action lockReleasedAction)
	{
		_lockAcquiredAction = lockAcquiredAction;
		_lockReleasedAction = lockReleasedAction;
	}

	/// <summary>
	/// 獲取鎖成功回調(diào)
	/// </summary>
	/// <returns></returns>
	public Task lockAcquired()
	{
		_lockAcquiredAction?.Invoke();
		return Task.FromResult(0);
	}

	/// <summary>
	/// 釋放鎖成功回調(diào)
	/// </summary>
	/// <returns></returns>
	public Task lockReleased()
	{
		_lockReleasedAction?.Invoke();
		return Task.FromResult(0);
	}
}

多線程模擬測(cè)試

static async Task RunAsync()
{
	Parallel.For(1, 10, async (i) =>
	{
		await new ZooKeeprDistributedLock().Lock("locks", () =>
		{
			Console.WriteLine($"第{i}個(gè)請(qǐng)求,獲取鎖成功:{DateTime.Now},線程Id:{Thread.CurrentThread.ManagedThreadId}");
			Thread.Sleep(1000); // 業(yè)務(wù)邏輯...
		}, () =>
		{
			Console.WriteLine($"第{i}個(gè)請(qǐng)求,釋放鎖成功:{DateTime.Now},線程Id:{Thread.CurrentThread.ManagedThreadId}");
			Console.WriteLine("-------------------------------");
		});
	});
	await Task.CompletedTask;
}

雖然模擬的是多線程并行執(zhí)行,但最終都會(huì)依賴鎖的獲取和釋放而串行執(zhí)行實(shí)際業(yè)務(wù)邏輯。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 全面分析c# LINQ

    全面分析c# LINQ

    這篇文章主要介紹了c# LINQ的相關(guān)資料,幫助大家更好的理解和使用c#,感興趣的朋友可以了解下
    2020-08-08
  • c# 重載WndProc,實(shí)現(xiàn)重寫(xiě)“最小化”的實(shí)現(xiàn)方法

    c# 重載WndProc,實(shí)現(xiàn)重寫(xiě)“最小化”的實(shí)現(xiàn)方法

    在做“亦歌桌面版”的時(shí)候,發(fā)現(xiàn)當(dāng)打開(kāi)歌詞狀態(tài)下,用最小化隱藏窗體到托盤(pán)的話(如下code #1),在調(diào)出發(fā)現(xiàn)歌詞縮小了(雖然顯現(xiàn)的窗體大小跟剛才一樣),從這點(diǎn)看調(diào)用該方法其實(shí)窗體大小是改變了的(這個(gè)過(guò)程只是不可視而已)。
    2009-02-02
  • C#+RedisSearch實(shí)現(xiàn)高性能全文搜索

    C#+RedisSearch實(shí)現(xiàn)高性能全文搜索

    Redis?Search是一個(gè)Redis模塊,它使用壓縮的倒排索引來(lái)實(shí)現(xiàn)快速的索引和低內(nèi)存占用,本文主要介紹了C#如何使用RedisSearch實(shí)現(xiàn)高性能全文搜索,希望對(duì)大家有所幫助
    2023-07-07
  • C# Winform實(shí)現(xiàn)自定義漂亮的通知效果

    C# Winform實(shí)現(xiàn)自定義漂亮的通知效果

    這篇文章主要介紹了C# Winform實(shí)現(xiàn)自定義漂亮的通知效果,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-08-08
  • C#中的composite模式示例詳解

    C#中的composite模式示例詳解

    Composite組合模式屬于設(shè)計(jì)模式中比較熱門(mén)的一個(gè),相信大家對(duì)它一定不像對(duì)訪問(wèn)者模式那么陌生,這篇文章主要介紹了C#中的composite模式,需要的朋友可以參考下
    2022-06-06
  • 詳解C#讀寫(xiě)Excel的幾種方法

    詳解C#讀寫(xiě)Excel的幾種方法

    這篇文章主要介紹了詳解C#讀寫(xiě)Excel的幾種方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • C# Xamarin利用ZXing.Net.Mobile進(jìn)行掃碼的方法

    C# Xamarin利用ZXing.Net.Mobile進(jìn)行掃碼的方法

    這篇文章主要介紹了C# Xamarin利用ZXing.Net.Mobile進(jìn)行掃碼的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-06-06
  • C#在驗(yàn)證文件共享模式下實(shí)現(xiàn)多線程文件寫(xiě)入

    C#在驗(yàn)證文件共享模式下實(shí)現(xiàn)多線程文件寫(xiě)入

    這篇文章主要為大家詳細(xì)介紹了C#在驗(yàn)證文件共享模式下實(shí)現(xiàn)多線程文件寫(xiě)入的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下
    2024-01-01
  • 總結(jié)C#刪除字符串?dāng)?shù)組中空字符串的幾種方法

    總結(jié)C#刪除字符串?dāng)?shù)組中空字符串的幾種方法

    C#中要如何才能刪除一個(gè)字符串?dāng)?shù)組中的空字符串呢?下面的文章會(huì)介紹多種方式來(lái)實(shí)現(xiàn)清除數(shù)組中的空字符串,以及在.net中將字符串?dāng)?shù)組中字符串為空的元素去除。
    2016-08-08
  • C#操作Windows服務(wù)類System.ServiceProcess.ServiceBase

    C#操作Windows服務(wù)類System.ServiceProcess.ServiceBase

    這篇文章介紹了C#操作Windows服務(wù)類System.ServiceProcess.ServiceBase,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-05-05

最新評(píng)論