大战熟女丰满人妻av-荡女精品导航-岛国aaaa级午夜福利片-岛国av动作片在线观看-岛国av无码免费无禁网站-岛国大片激情做爰视频

專注Java教育14年 全國咨詢/投訴熱線:400-8080-105
動力節點LOGO圖
始于2009,口口相傳的Java黃埔軍校
首頁 hot資訊 Redis分布式事務

Redis分布式事務

更新時間:2022-02-15 09:34:28 來源:動力節點 瀏覽1517次

redis 中的事務由放置在MULTI和EXEC(或DISCARD用于回滾)之間的命令塊組成。一旦MULTI 遇到 a ,該連接上的命令就不會被執行- 它們被排隊(并且調用者得到QUEUED 每個的回復)。當EXEC遇到 an 時,它們都被應用在一個單元中(即沒有其他連接在操作之間獲得時間)。如果DISCARD看到 a 而不是 a EXEC,則所有內容都將被丟棄。因為事務內部的命令是排隊的,所以你不能在事務內部做出決定 。例如,在 SQL 數據庫中,您可能會執行以下操作(偽代碼 - 僅用于說明):

// assign a new unique id only if they don't already
// have one, in a transaction to ensure no thread-races
var newId = CreateNewUniqueID(); // optimistic
using(var tran = conn.BeginTran())
{
	var cust = GetCustomer(conn, custId, tran);
	var uniqueId = cust.UniqueID;
	if(uniqueId == null)
	{
		cust.UniqueId = newId;
		SaveCustomer(conn, cust, tran);
	}
	tran.Complete();
}

那么如何在 Redis 中做到這一點呢?

這在 redis 事務中根本不可能:一旦事務打開,您就無法獲取數據- 您的操作已排隊。幸運的是,還有另外兩個命令可以幫助我們:WATCH和UNWATCH.

WATCH {key}告訴 Redis 我們對指定的鍵感興趣以用于事務。Redis 會自動跟蹤這個鍵,任何更改都會使我們的事務回滾 -EXEC與DISCARD(調用者可以檢測到這一點并從頭開始重試)相同。所以你可以做的是:WATCH一個鍵,以正常方式從那個鍵中檢查數據,然后MULTI/EXEC你的更改。如果,當您檢查數據時,您發現您實際上并不需要該事務,您可以使用UNWATCH忘記所有被監視的鍵??。請注意,監視的鍵也會在EXEC和期間重置DISCARD。所以在 Redis 層,這在概念上是:

WATCH {custKey}
HEXISTS {custKey} "UniqueId"
-- (check the reply, then either:)
MULTI
HSET {custKey} "UniqueId" {newId}
EXEC
-- (or, if we find there was already an unique-id:)
UNWATCH

這可能看起來很奇怪 - 有一個MULTI/EXEC只跨越一個操作 - 但重要的是我們現在也在跟蹤{custKey}所有其他連接的更改 - 如果其他任何人更改密鑰,事務將被中止。

在 StackExchange.Redis 中呢?

StackExchange.Redis 使用多路復用器方法這一事實使情況變得更加復雜。我們不能簡單地讓并發調用者發出WATCH/ UNWATCH/ MULTI/ EXEC/ DISCARD:它們都會混在一起。所以提供了一個額外的抽象——另外讓事情變得更簡單:約束。約束基本上是預先準備好的測試,包括WATCH、某種測試和對結果的檢查。如果所有約束都通過,則發出MULTI/ ;EXEC否則UNWATCH發出。這一切都是以防止命令與其他調用者混合在一起的方式完成的。所以我們的例子變成了:

var newId = CreateNewId();
var tran = db.CreateTransaction();
tran.AddCondition(Condition.HashNotExists(custKey, "UniqueID"));
tran.HashSetAsync(custKey, "UniqueID", newId);
bool committed = tran.Execute();
// ^^^ if true: it was applied; if false: it was rolled back

請注意,從返回的對象CreateTransaction只能訪問異步方法 - 因為每個操作的結果要等到Execute(或ExecuteAsync)完成之后才能知道。如果未應用操作,所有Tasks 將被標記為取消 - 否則,在命令執行后,您可以正常獲取每個結果。

可用條件的集合并不廣泛,但涵蓋了最常見的場景;如果您想查看其他條件,請與我聯系(或更好:提交拉取請求)。

內置操作通過When

還需要注意的是,Redis 已經預料到了許多常見的場景(特別是:key/hash 的存在,就像上面一樣),并且存在單操作原子命令。這些是通過When參數訪問的——所以我們前面的例子也可以寫成:

var newId = CreateNewId();
bool wasSet = db.HashSet(custKey, "UniqueID", newId, When.NotExists);

(這里是使用命令的When.NotExists原因,而不是)HSETNXHSET

Lua

您還應該記住,Redis 2.6 及更高版本支持 Lua 腳本,這是一種通用工具,用于在服務器上作為單個原子單元執行多個操作。由于在 Lua 腳本期間沒有為其他連接提供服務,它的行為很像一個事務,但沒有MULTI/EXEC等的復雜性。這也避免了調用者和服務器之間的帶寬和延遲等問題,但權衡是它壟斷了腳本期間的服務器。

在 Redis 層(假設HSETNX不存在),這可以實現為:

EVAL "if redis.call('hexists', KEYS[1], 'UniqueId') then return redis.call('hset', KEYS[1], 'UniqueId', ARGV[1]) else return 0 end" 1 {custKey} {newId}

這可以通過以下方式在 StackExchange.Redis 中使用:

var wasSet = (bool) db.ScriptEvaluate(@"if redis.call('hexists', KEYS[1], 'UniqueId') then return redis.call('hset', KEYS[1], 'UniqueId', ARGV[1]) else return 0 end",
        new RedisKey[] { custKey }, new RedisValue[] { newId });

(請注意,來自ScriptEvaluateand的響應ScriptEvaluateAsync是可變的,具體取決于您的確切腳本;響應可以通過強制轉換來解釋 - 在這種情況下為 a bool)

通過上述相信大家對Redis分布式事務已經有所了解,大家如果對此比較感性趣,想了解更多相關知識,不妨來關注一下動力節點的Redis教程,里面的課程內容從淺到深,通俗易懂,適合沒有基礎的朋友學習,希望對大家能夠有所幫助。

提交申請后,顧問老師會電話與您溝通安排學習

免費課程推薦 >>
技術文檔推薦 >>
主站蜘蛛池模板: 久久国产精品网 | 狠狠久久综合伊人不卡 | 国内久久精品 | 国产成人精品日本亚洲专一区 | 亚洲在线观看一区二区 | 站长推荐国产午夜免费视频 | 日韩亚射 | 在线精品国精品国产不卡 | 亚洲视频一区在线 | 亚洲国产精品日韩高清秒播 | 久久国内精品自在自线观看 | 免费费看的欧亚很色大片 | 国产尤物精品视频 | 亚洲图片欧美日韩 | 性色网站 | 久久91精品国产91久久户 | 亚洲精品字幕一区二区三区 | 久久黄色录像 | 国产日韩高清一区二区三区 | 日本二三区 | 欧美亚洲另类色国产综合 | 女人18毛片a级毛片 女人18毛片a级毛片免费 | 久久日韩精品中文字幕网 | 国产日韩片 | 久久99精品久久久久久野外 | 亚洲无总热门 | 奇米第四色视频 | 极品粉嫩粉嫩福利视频在线 | 国产一区 在线视频 | 日韩免费一级毛片欧美一级日韩片 | 韩国欧美一级毛片免费 | 日本乱中文字幕系列在线观看 | 国产高清专区 | 国产成人久久精品一区二区三区 | 四虎8848精品永久在线观看 | 午夜精品久久久久久久99热浪潮 | 婷婷 综合 | 奇米视频7777 | 福利岛国深夜在线 | 狠狠色丁香久久婷婷综合丁香 | 欧美成人欧美激情欧美风情 |