我們在開發時,有時會碰到乙個介面的訪問量突然上公升,導致服務響應延遲或者宕機的情況。這時,除了利用快取之外,也可以用到singlefilght
來解決,下面是乙個簡單的示例
package main
import
("fmt"
"sync"
"sync/atomic"
"time"
"golang.org/x/sync/singleflight"
)func
main()
wg := sync.waitgroup
for i :=
0; i <
100; i++
fmt.
printf
("index: %d, val: %d, shared: %v\n"
, j, val, shared)
}(i)
} wg.
wait()
}var
( count =
int64(0
))// 模擬介面方法
funca(
)(inte***ce
,error
)// 部分輸出,shared表示是否共享了其他請求的返回結果
index:
2, val:
1, shared:
false
index:
71, val:
1, shared:
true
index:
69, val:
1, shared:
true
index:
73, val:
1, shared:
true
index:
8, val:
1, shared:
true
index:
24, val:
1, shared:
true
val
這裡絕大部分都為1
是因為程式執行時間太快了,可以試著把time.sleep
時間縮短一點看看效果
singleflight
核心**非常簡單
// 成員非常少,就兩個
type group struct
func
(g *group)
do(key string
, fn func()
(inte***ce
,error))
(v inte***ce
, err error
, shared bool
)// 判斷key是否存在,存在則表示有其他請求先一步進來,
// 直接等待其他請求返回就行
if c, ok := g.m[key]
; ok
// 不存在就建立乙個新的call物件,然後去執行
c :=
new(call)
c.wg.
add(1)
g.m[key]
= c g.mu.
unlock()
g.docall
(c, key, fn)
return c.val, c.err, c.dups >
0}
docall
方法很簡單,這裡就不展開了,除了do
方法之外,還有乙個非同步的dochan
方法,原理一模一樣。
我們一般可以在一些類似於冪等的介面上用singleflight
它原始碼非常短,有需要的可以去展開閱讀,**思路非常清楚
redis快取擊穿
1 快取擊穿出現的場景 我們知道redis的資料是儲存在記憶體的,而記憶體是有限的,所以一般會設定過期時間,當某個key過期了,而此時大量的併發來請求這個key,導致都去請求mysql啦,而mysql的併發連線數很低,缺少了redis這層盾牌,mysql自然扛不住,這不是架構的問題,因為之前的架構中...
Redis快取擊穿
什麼是快取擊穿 key對應的資料存在,但是在redis中key過期了,此時如有大量的併發請求過來,這些請求發現快取過期一般都會從後端伺服器載入資料並回設到快取,這個時候大併發請求可能會瞬間把後端db壓垮 如圖 出現快取穿透的特點 1.資料庫訪問壓力瞬間增加 2.redis裡面出現大量key過期 3....
快取穿透 快取擊穿 快取雪崩
一 快取處理流程 前台請求,後台先從快取中取資料,取到直接返回結果,取不到時從資料庫中取,資料庫取到更新快取,並返回結果,資料庫也沒取到,那直接返回空結果。二 快取穿透 描述 快取穿透是指快取和資料庫中都沒有的資料,而使用者不斷發起請求,如發起為id為 1 的資料或id為特別大不存在的資料。這時的使...