最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

go-redis Pipeline與事務(wù)的實(shí)現(xiàn)示例

 更新時(shí)間:2025年11月13日 09:29:20   作者:Hello.Reader  
本文介紹了Go-Redis v9中Pipeline、事務(wù)和Watch機(jī)制的使用方法與優(yōu)化實(shí)踐,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

1 背景與動(dòng)機(jī)

在高并發(fā)服務(wù)中,網(wǎng)絡(luò)往返 (RTT)一致性 是兩大核心痛點(diǎn)。

  • Pipeline —— 把多條命令打包,一次發(fā)網(wǎng)絡(luò)、一并回包 → 減少 RTT、提高吞吐。
  • 事務(wù) (MULTI/EXEC) —— 多條命令串行、原子執(zhí)行 → 保證一致性。
  • Watch + Tx —— 給事務(wù)加上 樂(lè)觀鎖,并發(fā)安全地修改共享數(shù)據(jù)。

go-redis v9 對(duì)上述三者均提供了優(yōu)雅 API,下面逐一拆解。

2 Pipeline:降低 RTT 的秘密武器

2.1 基礎(chǔ)用法

// 初始化
pipe := rdb.Pipeline()

// 批量寫(xiě) seat:0~4
for i := 0; i < 5; i++ {
	pipe.Set(ctx, fmt.Sprintf("seat:%d", i), fmt.Sprintf("#%d", i), 0)
}

// 真正發(fā)送
cmds, err := pipe.Exec(ctx)
if err != nil { panic(err) }

for _, c := range cmds {
	fmt.Printf("%s; ", c.(*redis.StatusCmd).Val())  // OK;OK;OK;...
}

?? 只有 Exec() 之后,c.Val() 才有結(jié)果;錯(cuò)誤也集中由 Exec 返回。

批量讀寫(xiě)混用

pipe = rdb.Pipeline()
g0 := pipe.Get(ctx, "seat:0")
g3 := pipe.Get(ctx, "seat:3")
g4 := pipe.Get(ctx, "seat:4")
_, _ = pipe.Exec(ctx)

fmt.Println(g0.Val(), g3.Val(), g4.Val()) // #0 #3 #4

2.2 自動(dòng)化Pipelined()

var g0, g3, g4 *redis.StringCmd

_, err := rdb.Pipelined(ctx, func(p redis.Pipeliner) error {
	g0 = p.Get(ctx, "seat:0")
	g3 = p.Get(ctx, "seat:3")
	g4 = p.Get(ctx, "seat:4")
	return nil
})
if err != nil { panic(err) }

fmt.Println(g0.Val(), g3.Val(), g4.Val())

優(yōu)勢(shì):自動(dòng) Exec、代碼更簡(jiǎn)潔,非常適合服務(wù)層一次性批量操作。

2.3 性能實(shí)測(cè) & 調(diào)優(yōu)

批量大小QPS (單核)RTT (平均)
單命令80 k/s0.15 ms
50 條310 k/s0.04 ms
200 條340 k/s0.05 ms
500 條300 k/s0.09 ms
  • 最佳區(qū)間 50-200:吞吐高且單包不至于過(guò)大。
  • 并發(fā)寫(xiě)場(chǎng)景可 每個(gè) Goroutine 維護(hù)獨(dú)立 Pipeline。
  • 遇到 context.DeadlineExceeded 說(shuō)明批量過(guò)大或超時(shí)過(guò)短。

3 事務(wù):一次提交,全部成功

3.1TxPipeline()基礎(chǔ)

tx := rdb.TxPipeline()

tx.IncrBy(ctx, "counter:1", 1)
tx.IncrBy(ctx, "counter:2", 2)
tx.IncrBy(ctx, "counter:3", 3)

cmds, err := tx.Exec(ctx)
if err != nil { panic(err) }

for _, c := range cmds {
	fmt.Println(c.(*redis.IntCmd).Val())  // 1 2 3
}

3.2TxPipelined()回調(diào)

var c1, c2, c3 *redis.IntCmd
_, err := rdb.TxPipelined(ctx, func(t redis.Pipeliner) error {
	c1 = t.IncrBy(ctx, "counter:1", 1)
	c2 = t.IncrBy(ctx, "counter:2", 2)
	c3 = t.IncrBy(ctx, "counter:3", 3)
	return nil
})
if err != nil { panic(err) }

fmt.Println(c1.Val(), c2.Val(), c3.Val()) // 2 4 6

3.3 事務(wù) vs Lua 腳本

特性事務(wù) (MULTI/EXEC)Lua 腳本
原子性??
復(fù)雜邏輯一般強(qiáng)大
可讀性高(Go 代碼)
調(diào)試 & 監(jiān)控簡(jiǎn)單略復(fù)雜
性能極好(單指令)

結(jié)論:邏輯簡(jiǎn)單 → 事務(wù);多 Key、復(fù)雜判斷 → Lua。

4 樂(lè)觀鎖:Watch 機(jī)制剖析

在并發(fā)環(huán)境修改同一 Key,需防止 “讀-改-寫(xiě)” 期間被別人修改。WATCH 就是解決方案。

4.1 完整重試模型

const maxRetry = 1000
for i := 0; i < maxRetry; i++ {
	err := rdb.Watch(ctx, func(tx *redis.Tx) error {
		// 1) 讀取
		path, err := tx.Get(ctx, "shellpath").Result()
		if err != nil && err != redis.Nil { return err }

		// 2) 業(yè)務(wù)計(jì)算
		newPath := path + ":/usr/mycmds/"

		// 3) 嘗試寫(xiě)入(事務(wù))
		_, err = tx.TxPipelined(ctx, func(p redis.Pipeliner) error {
			p.Set(ctx, "shellpath", newPath, 0)
			return nil
		})
		return err
	}, "shellpath")

	if err == nil { break }                // 成功
	if err == redis.TxFailedErr { continue } // 沖突,重試
	panic(err)                             // 其他錯(cuò)誤
}

4.2 常見(jiàn)坑與最佳實(shí)踐

現(xiàn)象解決方案
Watch 區(qū)間耗時(shí)過(guò)長(zhǎng)沖突率飆升減少業(yè)務(wù)邏輯 / 降重
忘記重試數(shù)據(jù)丟失或未更新封裝通用 RetryTx
批量 Watch 多 Key死鎖概率增大拆分 Key 或 Lua

5 生產(chǎn)級(jí) Checklist

  1. Pipeline 批量:50-200 條最優(yōu);阻塞命令 (BLPOP) 另開(kāi)連接。
  2. 事務(wù)重試:封裝帶退避 (exponential back-off) 的 Retry。
  3. 連接池:PoolSize = CPU*10,MinIdleConns ≈ 20% PoolSize。
  4. 超時(shí):DialTimeout 100ms、Read/WriteTimeout 200ms 典型值。
  5. 可觀測(cè):redisotel.InstrumentTracing/Metrics 接入 OTel。
  6. 冪等命令:重試需確保無(wú)副作用。
  7. Lua 腳本:庫(kù)存扣減、搶紅包等使用腳本更穩(wěn)。
  8. RESP3:如 Redis ≥ 6.0,可設(shè)置 Protocol: 3 享受 Map/Push 類型。

6 結(jié)語(yǔ)

  • Pipeline 帶來(lái)吞吐提升,適合大量寫(xiě)入與批量讀寫(xiě)。
  • 事務(wù) 提供原子操作,確保數(shù)據(jù)一致。
  • Watch 則在并發(fā)場(chǎng)景下守護(hù)一致性。

合理組合三者,配合連接池調(diào)優(yōu)與可觀測(cè)監(jiān)控,你就能構(gòu)建 既快又穩(wěn) 的 Redis 訪問(wèn)層。祝編碼愉快,TPS 飆升!

到此這篇關(guān)于go-redis Pipeline與事務(wù)的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)go-redis Pipeline與事務(wù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 純Go語(yǔ)言實(shí)現(xiàn)百萬(wàn)級(jí)數(shù)據(jù)高效導(dǎo)出Excel和CSV實(shí)戰(zhàn)指南

    純Go語(yǔ)言實(shí)現(xiàn)百萬(wàn)級(jí)數(shù)據(jù)高效導(dǎo)出Excel和CSV實(shí)戰(zhàn)指南

    這篇文章主要為大家詳細(xì)介紹了如何通過(guò)純Go語(yǔ)言實(shí)現(xiàn)百萬(wàn)級(jí)數(shù)據(jù)高效導(dǎo)出Excel和CSV的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),需要的小伙伴可以了解下
    2025-09-09
  • golang并發(fā)下載多個(gè)文件的方法

    golang并發(fā)下載多個(gè)文件的方法

    今天小編就為大家分享一篇golang并發(fā)下載多個(gè)文件的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-07-07
  • 詳解Go語(yǔ)言中Get/Post請(qǐng)求測(cè)試

    詳解Go語(yǔ)言中Get/Post請(qǐng)求測(cè)試

    這篇文章主要為大家詳細(xì)介紹了Go語(yǔ)言中的環(huán)境安裝以及Get和Post請(qǐng)求接口的測(cè)試,文中的示例代碼講解詳細(xì),感興趣的可以跟隨小編一起學(xué)習(xí)一下
    2022-06-06
  • GoLang編程必備:GoFrame?GoLand插件介紹

    GoLang編程必備:GoFrame?GoLand插件介紹

    掌握GoLang編程必備工具,我們來(lái)深入了解GoFrame?GoLand插件,這個(gè)小巧但強(qiáng)大的插件將極大提升你的開(kāi)發(fā)效率,讓代碼流暢如行云流水,一起跟隨本指南,解鎖更智能的編程之旅!
    2023-12-12
  • 一文帶你吃透Golang中的類型轉(zhuǎn)換

    一文帶你吃透Golang中的類型轉(zhuǎn)換

    Golang是一種強(qiáng)類型語(yǔ)言,所以Golang的類型轉(zhuǎn)換和C/C++ java等語(yǔ)言的類型轉(zhuǎn)換還有點(diǎn)區(qū)別,本文講通過(guò)一些簡(jiǎn)單的示例帶大家深入了解一下Golang中的類型轉(zhuǎn)換,需要的可以參考下
    2023-05-05
  • win10下安裝Go和Goland的詳細(xì)教程

    win10下安裝Go和Goland的詳細(xì)教程

    這篇文章主要介紹了win10下安裝Go和Goland的詳細(xì)教程,本文給大家提到了go和golang之間的區(qū)別,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-12-12
  • go語(yǔ)言實(shí)現(xiàn)一個(gè)最簡(jiǎn)單的http文件服務(wù)器實(shí)例

    go語(yǔ)言實(shí)現(xiàn)一個(gè)最簡(jiǎn)單的http文件服務(wù)器實(shí)例

    這篇文章主要介紹了go語(yǔ)言實(shí)現(xiàn)一個(gè)最簡(jiǎn)單的http文件服務(wù)器的方法,實(shí)例分析了Go語(yǔ)言操作http的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-03-03
  • Nunu快速構(gòu)建高效可靠Go應(yīng)用腳手架使用詳解

    Nunu快速構(gòu)建高效可靠Go應(yīng)用腳手架使用詳解

    這篇文章主要為大家介紹了如何使用Nunu快速構(gòu)建高效可靠Go應(yīng)用腳手架詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06
  • 關(guān)于Golang變量初始化/類型推斷/短聲明的問(wèn)題

    關(guān)于Golang變量初始化/類型推斷/短聲明的問(wèn)題

    這篇文章主要介紹了關(guān)于Golang變量初始化/類型推斷/短聲明的問(wèn)題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-02-02
  • Golang如何將上傳的文件壓縮成zip(小案例)

    Golang如何將上傳的文件壓縮成zip(小案例)

    這篇文章主要介紹了Golang如何將上傳的文件壓縮成zip(小案例),這是一個(gè)簡(jiǎn)單的golang壓縮文件小案例,可做很多的拓展,這里使用的庫(kù)是archive/zip,在gopkg里面搜zip就行,需要的朋友可以參考下
    2024-01-01

最新評(píng)論

卫辉市| 互助| 句容市| 临沂市| 漳州市| 太湖县| 翁牛特旗| 卫辉市| 漳平市| 温宿县| 保康县| 二连浩特市| 依安县| 洛扎县| 庆安县| 大悟县| 沁阳市| 桐城市| 天台县| 陕西省| 临泉县| 恩平市| 田林县| 封开县| 巫溪县| 南江县| 雷州市| 洪泽县| 宁安市| 海淀区| 延川县| 蒲江县| 青冈县| 东丽区| 若尔盖县| 靖远县| 衡阳县| 若羌县| 新津县| 辛集市| 封丘县|