# tuanCache **Repository Path**: aisleeppppp/tuan-cache ## Basic Information - **Project Name**: tuanCache - **Description**: 用go实现的分布式缓存 - **Primary Language**: Go - **License**: GPL-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-11-24 - **Last Updated**: 2021-12-07 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # tuanCache #### :tw-1f4cc: 介绍 用go实现的分布式缓存。参考学习了groupcache的实现,[geektutu.com](https://geektutu.com)的学习教程,在此感谢无私的付出😘 😊 #### :tw-1f4cf: 使用说明 1. clone或下载此package 2. 在本地创建一个文件夹,将clone或下载下来的文件放入创建的文件夹中 3. 在创建的文件夹目录下创建main.go,引用tuanCache 4. main.go的内容可以参考如下: ```go package main import ( "flag" "fmt" "log" "net/http" "tuanCache" ) var db = map[string]string { "hhh": "111", "yyy": "222", "lll": "333", } func createGroup() *tuanCache.Group { log.Println("+++Create Group") return tuanCache.NewGroup("scores", 2<<10, tuanCache.GetterFunc( func(key string) ([]byte, error) { log.Println("+++in GetterFunc callback function") log.Println("[SlowDB] search key", key) if v, ok := db[key]; ok { return []byte(v), nil } return nil, fmt.Errorf("%s not exist", key) })) } //启动缓存服务器,创建HTTPPool,添加节点信息,注册到tuan中,启动HTTP服务 //用户不感知 func startCacheServer(addr string, addrs []string, tuan *tuanCache.Group) { peers := tuanCache.NewHTTPPool(addr) peers.Set(addrs...) tuan.RegisterPeers(peers) log.Println("tuanCache is running at", addr) log.Fatal(http.ListenAndServe(addr[7:], peers)) } //启动一个api服务,与用户交互,用户感知 func startAPIServer(apiAddr string, tuan *tuanCache.Group) { log.Println("+++in startAPIServer function") http.Handle("/api", http.HandlerFunc( func(w http.ResponseWriter, r *http.Request) { log.Println("+++in startAPIServer's HandlerFunc function") key := r.URL.Query().Get("key") view, err := tuan.Get(key) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } w.Header().Set("Content-Type", "application/octet-stream") w.Write(view.ByteSlice()) })) log.Println("frontend server is running at", apiAddr) log.Fatal(http.ListenAndServe(apiAddr[7:], nil)) } func main() { var port int var api bool flag.IntVar(&port, "port", 8001, "tuanCache server port") flag.BoolVar(&api, "api", false, "Start a api server?") flag.Parse() apiAddr := "http://localhost:9999" addrMap := map[int]string{ 8081: "http://localhost:8081", 8082: "http://localhost:8082", 8083: "http://localhost:8083", } var addres []string for _, v := range addrMap { addres = append(addres, v) } tuan := createGroup() if api { go startAPIServer(apiAddr, tuan) } startCacheServer(addrMap[port], []string(addres), tuan) } ``` 服务端起了三个端口号,可以用来测试一致性哈希和singleflight的使用 5. 在此文件夹下运行`go mod init`生成go.mod文件 6. 在新创建的文件夹下创建run.sh脚本,内容可以参考如下: ```sh #!/bin/bash trap "rm server;kill 0" EXIT go build -o server ./server -port=8081 & ./server -port=8082 & ./server -port=8083 -api=1 & sleep 2 echo ">>> start test" curl "http://localhost:9999/api?key=hhh" & curl "http://localhost:9999/api?key=hhh" & curl "http://localhost:9999/api?key=hhh" & wait ``` 7. 运行 ./run.sh #### :tw-1f3c6: 参与贡献 1. Fork 本仓库 2. 新建 Feat_xxx 分支 3. 提交代码 4. 新建 Pull Request #### :tw-1f52f: 特技 使用LRU缓存策略 单机缓存和基于HTTP的分布式缓存 使用WaitGroup防止缓存击穿 使用一致性哈希选择节点,实现负载均衡