Singleflight Pattern
Singleflight naqshi
Tasavvur qiling, bir vaqtning o'zida 100 ta foydalanuvchi bir xil, hali keshda yo'q ma'lumotni (masalan "bugungi valyuta kursi") so'rayapti. Agar har biri uchun alohida, bazaga yoki tashqi API'ga so'rov yuborilsa — bu 100 marta bir xil ishni takrorlash, resursni behuda sarflash degani.
Singleflight naqshi buni hal qiladi: agar bir xil "kalit" uchun so'rov allaqachon bajarilayotgan bo'lsa, keyingi so'rovlar yangi ish boshlamaydi — ular birinchi so'rov tugashini kutib, bitta natijani hammasi baham ko'radi. Bu — navbatda turgan 100 kishi bittasi "men hammaga sotib olib kelaman" deb, faqat bir marta do'konga borishga o'xshaydi.
package main
import (
"fmt"
"sync"
"sync/atomic"
"time"
"golang.org/x/sync/singleflight"
)
func main() {
var g singleflight.Group
var callCount int64
var wg sync.WaitGroup
fetch := func() (interface{}, error) {
atomic.AddInt64(&callCount, 1)
time.Sleep(20 * time.Millisecond) // "sekin" tashqi so'rovni simulyatsiya qilish
return "natija", nil
}
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
defer wg.Done()
g.Do("same-key", fetch)
}()
}
wg.Wait()
fmt.Println(atomic.LoadInt64(&callCount))
}10 ta goroutine bir vaqtda g.Do("same-key", fetch) chaqiradi, lekin fetchning o'zi faqat bir marta bajariladi! singleflight.Group "same-key" uchun so'rov allaqachon bajarilayotganini ko'rib, qolgan 9 tasini yangi ish boshlashdan to'xtatadi — ular birinchisi tugashini kutib, xuddi shu natijani olishadi.
fetch ichidagi sun'iy time.Sleep ataylab qo'shilgan: agar so'rovlar bir zumda tugasa, ularning "bir vaqtda bajarilishi" imkoniyati kamayadi (birinchisi ulgurib tugab ketishi mumkin). Haqiqiy loyihada bu kechikish — tashqi API'ga yoki bazaga haqiqiy so'rov vaqti bo'lardi, va aynan shu "sekin" davrda singleflight eng katta foyda beradi: keshi "issiq bo'lmagan" (cache miss) paytda kelib tushgan yuzlab bir xil so'rovni bittaga tushiradi.
>_ Exercise
Ikkita XIL kalit uchun singleflight'ning alohida ishlashini tekshiring.
- •5 ta goroutine "key-a" bilan, 5 ta goroutine "key-b" bilan g.Do chaqirsin
- •har ikkala guruh ham fetch funksiyasini chaqirsin (u callCount'ni oshiradi va 20ms kutadi)
- •yakunida callCount'ni chop eting (ikkita xil kalit borligi uchun natija 2 bo'lishi kerak)
Stuck? Reveal a hint to help you.
Key Takeaway
Key Takeaway:
Singleflight bir xil kalit uchun bir vaqtda kelgan takroriy so'rovlarni bitta haqiqiy bajarishga "siqib", natijani hammasiga baham beradi — bu keshi "sovuq" paytdagi ortiqcha yukni sezilarli kamaytiradi.
$ go run main.go
Kodingizni ishga tushiring