groupcache 架構設計
groupcache 是一個分散式快取 go 語言庫,支援多節點互備熱資料,有良好的穩定性和較高的併發性。
這裡有個簡單的應用場景:
當 GET foo 打到 groupcache-1 後:
- groupcache-1 先看看自己的 cache 裡有沒有 foo,有的話直接返回
- 要是沒有,看看這個請求歸不歸自己管,若是,去 DataSever 獲取,否則問 group-2(假設 foo 歸 -2 管) 要資料,成功返回後 groupcache-1 本地也快取一份
- 在 2 過程中,所有後來打到 groupcache-1 的 GET foo 都會阻塞,直到第一個請求返回
問題來了,如何判斷 foo 由誰來處理?
如上圖,利用 hash 將所有節點平均打散到全集,然後當 foo 進來後用相同 hash 演算法就會得到一個唯值,落在那個區間就屬於那個節點,要保證一致性。
因為 foo 和某資源一一對應,這就要求 groupcache 只有 get 沒有 update。
一個簡單的 HTTP groupcache Server:
package main
import "github.com/golang/groupcache"
import "github.com/gin-gonic/gin"
import "net/http"
import "time"
import "bytes"
// 虛擬檔案生成方法
func generateThumbnail(fileName string) []byte {
return []byte("fake file")
}
func main() {
// 本機 ip
me := "http://10.0.0.1"
peers := groupcache.NewHTTPPool(me)
// 設定互備的 node
peers.Set("http://10.0.0.1", "http://10.0.0.2", "http://10.0.0.3")
// 建立一個 cache group,最大快取為64M
var thumbNails = groupcache.NewGroup("thumbnail", 64<<20, groupcache.GetterFunc(
func(ctx groupcache.Context, key string, dest groupcache.Sink) error {
fileName := key
dest.SetBytes(generateThumbnail(fileName))
return nil
}))
// 設定 thumbnail 的 peers
groupcache.RegisterPeerPicker(func() groupcache.PeerPicker {
return peers
})
// 起一個 HTTP server
server := gin.Default()
server.GET("/files/:name", gin.HandlerFunc(
func(ctx *gin.Context) {
var data []byte
name := ctx.Param("name")
// 獲取快取
err := thumbNails.Get(ctx, name, groupcache.AllocatingByteSliceSink(&data))
if err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"mesage": "file not found"})
return
}
// 返回給客戶端
http.ServeContent(ctx.Writer, ctx.Request, name, time.Now(), bytes.NewReader(data))
}))
server.Run("10.0.0.1:80")
}
Group
groupcache.NewGroup(addr string)
Group 代表一個 cache 資源庫
type Group struct {
name string
getter Getter // cache 沒有命中,從資料庫獲取
peersOnce sync.Once
peers PeerPicker // peer 節點排程器
cacheBytes int64 // 最大cache位元組數
mainCache cache // 此節點快取
hotCache cache // 其他節點快取
loadGroup flightGroup // 請求併發控制器
Stats Stats // 統計資料
}
對於一個 Group 來說,會快取自己節點的資料和訪問比較頻繁的 peer 節點 的資料,用 LRU 演算法控制快取。
當 cache 沒有命中的時候,首先看看這個請求歸不歸該節點管,若是就是呼叫 getter:
Getter
type Getter interface {
Get(ctx Context, key string, dest Sink) error
}
對於一個 cache 來說,他不知道如何拉取需要快取的資料,所以他說啊,你要是想快取新的東西,就得有個 type 實現 Getter 介面,然後給我一個 Getter 物件,這樣 cache 沒有命中的時候我能靠這個物件拉取資料。
這個 Getter 類似於 http.Handler,抽象拉取要快取的資料這個行為,Context(interface{}) 是操作的附帶資訊,key 請求的 id,Sink 類似於 http.ResponseWriter,抽象了資料載體的行為:
Sink
type Sink interface {
// SetString 寫入 string
SetString(s string) error
// SetBytes 寫入位元組陣列,呼叫者會保留 v 引用
SetBytes(v []byte) error
// SetProto 寫入proto.Message,呼叫者會保留 m 應用
SetProto(m proto.Message) error
// ...
}
groupcache 提供了一些常用的 Sink 如 StringSink,BytesSliceSink 和 ProtoSink,這個 proto 是github.com/golang/protobuf/proto
,groupcache 規定內部 peer 節點之間資料通訊格式使用 google/protobuf,為了抽象 peer 節點,定義了 ProtoGetter:
ProtoGetter
type ProtoGetter interface {
Get(context Context, in *pb.GetRequest, out *pb.GetResponse) error
}
pb.GetRequest
和 pb.GetResponse
定義了請求和響應 struct,這個抽象可以分離底層傳輸方式。
當然還需要對節點排程器抽象,PeerPicker:
PeerPicker
type PeerPicker interface {
// PickPeer 根據 key 返回應該處理這個 key 的節點
// ok 為 true 代表找到了節點
// nil, false 代表當前節點就是 key 的處理器
PickPeer(key string) (peer ProtoGetter, ok bool)
}
排程器主要負責根據管理 key 和節點的一致性對映。
groupcache 實現了一個 HTTP 的 PeerPicker,HTTPPool。
至此,groupcache 通過 Getter,PeerPicker,ProtoGetter 三個 interface 定義了 cache,節點和排程器之間的連線方式,可以有效地控制耦合度,也提供了比較大的靈活性。
- 加微信實戰群請加微信(註明:實戰群):gocnio
相關文章
- 架構設計思想-微服務架構設計模式架構微服務設計模式
- 架構設計架構
- 遊戲架構 遊戲架構設計(8)遊戲架構
- Nginx架構設計Nginx架構
- Tumblr 架構設計架構
- 架構與設計架構
- 架構設計之一——基礎架構架構
- 架構設計之架構的演變架構
- 架構師修煉之道(二)——架構?設計?架構師?架構
- SaaS架構:開放平臺架構設計架構
- 網站架構設計網站架構
- 架構設計方法論架構
- 面向架構程式設計架構程式設計
- 架構設計(九):估算架構
- 架構設計方法初探架構
- MVP架構設計 初探MVP架構
- 軟體架構設計架構
- WebService Soap架構設計Web架構
- 架構、框架、設計模架構框架
- 學習架構設計架構
- 企業架構設計?架構
- 如何設計app架構?APP架構
- 常用的設計架構架構
- 軟體架構設計原則和模式(上):分層架構設計架構模式
- spark架構設計&程式設計模型01Spark架構程式設計模型
- 讀《前端架構設計》 兼談架構與框架前端架構框架
- SaaS架構:多租戶系統架構設計架構
- SaaS架構:中央庫存系統架構設計架構
- 【Apollo】(2)--- Apollo架構設計架構
- 秒殺架構模型設計架構模型
- Fresco架構設計賞析架構
- 小程式渲染架構設計架構
- UI架構設計的演化UI架構
- 如何精心設計CDN架構架構
- 理解Underscore的設計架構架構
- Dubbo架構設計詳解架構
- 事件驅動架構設計事件架構
- 流程引擎的架構設計架構