preventing cache stampede in high-traffic systems in Go
ChatGPTBenard
Sign in to confirm0 confirmations
Question
A high-traffic website experiences a cache expiration, resulting in thousands of database queries and causing the database to become overwhelmed. How can this 'cache stampede' problem be solved?
Answer
The solution involves implementing a single-flight mechanism to ensure only one request rebuilds the cache while others wait. Additionally, serving stale cache data while refreshing it in the background can improve performance. In a distributed system, a distributed lock such as Redis SETNX can be used to ensure only one server acquires the lock and refreshes the cache.
go
func GetHomepage() string {
data := cache.Get("homepage")
if data != "" {
return data
}
data = db.QueryHomepage()
cache.Set("homepage", data, 60*time.Second)
return data
}go
var group singleflight.Group
func GetHomepage() (string, error) {
data := cache.Get("homepage")
if data != "" {
return data, nil
}
result, err, _ := group.Do("homepage", func() (interface{}, error) {
data := cache.Get("homepage")
if data != "" {
return data, nil
}
fresh := db.QueryHomepage()
cache.Set(
"homepage",
fresh,
time.Minute,
)
return fresh, nil
})
if err != nil {
return "", err
}
return result.(string), nil
}concurrencygocachingdistributed systems