Redis 在 Go 項目中的集成和統(tǒng)一管理
本節(jié)我們在項目中安裝和集成 go-redis,讓項目能訪問Redis,后面實戰(zhàn)項目中的用戶認證體系會依賴Redis來實現,像Token、Session這些都是在Redis中存儲的。
本節(jié)大綱如下:
圖片
Redis的使用場景有不少,不過有一點需要提醒的是別把Redis當數據庫用哦。
這里分享一篇 Redis應用場景匯總,里面羅列了十幾個場景,大家有興趣的可以看一下。
go-redis 的安裝和配置
在我們的Go項目里訪問Redis使用的是 go-redis 這個包,之前也見過一些項目使用redigo 來訪問Redis,不過redigo已經停止維護了,所以就不考慮使用它了。
安裝 go-redis 使用以下命令
go get github.com/redis/go-redis/v9
安裝過程中會向項目依賴中添加下面這些包,在gomod 文件中也會看到它們的身影。
圖片
依賴下載完成后,我們先不著急去初始化它,還是先把相關的配置先在配置文件里寫好。在 applicaiton.dev.yaml 增加Redis相關配置。
redis: # 記得更改成自己的連接配置
addr: 127.0.0.1:31379
password: 123456
pool_size: 10
db: 0
其他兩個環(huán)境的配置文件建議也先加上,避免配置文件之間結構和字段相差太多,等有測試和生產環(huán)境后再把配置調整過去即可。
配置添加完后,我們在 config.go 中增加 Redis 這些配置字段的對應的類型定義
var (
...
Redis *redisConfig
)
// Redis 配置
type redisConfig struct {
Addr string `mapstructure:"addr"`
Password string `mapstructure:"password"`
PoolSize int `mapstructure:"pool_size"`
DB int `mapstructure:"db"`
}
同時也在 bootstrap.go 中把config文件中的redis配置字段映射到 redisConfig 類型的變量 config.Redis上
func init() {
env := os.Getenv("ENV")
vp := viper.New()
...
vp.UnmarshalKey("redis", &Redis)
}
配置做好后,接下來我們在 dal/cache 目錄中新建redisinit.go 文件,在其中對go-redis客戶端進行初始化
var redisClient *redis.Client
func Redis() *redis.Client {
return redisClient
}
func init() {
redisClient = redis.NewClient(&redis.Options{
Addr: config.Redis.Addr,
Password: config.Redis.Password,
DB: config.Redis.DB,
PoolSize: config.Redis.PoolSize,
DialTimeout: 10 * time.Second,
ReadTimeout: 30 * time.Second,
WriteTimeout: 30 * time.Second,
PoolTimeout: 30 * time.Second,
})
if err :=redisClient.Ping(context.Background()).Err(); err != nil {
// 連接不上redis 讓項目停止啟動
panic(err)
}}
跟初始化GORM時一樣,如果你不想用Go的init機制,這里可以把這個初始化方法修改名成InitRedis,到main函數中去調用它來手動完成初始化。
Redis Key 的管理
我們在使用Redis的時候,最好把Key 放在項目里統(tǒng)一的地方進行管理,同時在命名時給Key加上包含業(yè)務、項目、模塊信息的前綴名,通過簽證在查問題的時候我們最起碼能快速定位到緩存是哪個項目寫進去的。
我在平時維護項目中被 Redis 搞的頭大的大部分情況是,很多舊代碼在A項目里緩存了個什么數據,然后到下游的B項目再去讀這個數據,根據緩存里數據的狀態(tài)執(zhí)行不同的邏輯分支。
有的時候監(jiān)控系統(tǒng)報告B項目出了Bug,查問題看到從Redis里讀取到的數據跟預想的不一樣,一般人都會先在B項目中Debug,看下緩存設置的程序是不是有問題,但是針對這種情況把整個B項目搜遍也沒發(fā)現緩存是從哪里存進去的。
所以 Redis Key 的命名不能太隨意,最好包含設置緩存的項目名、所屬業(yè)務等能確定緩存來源的信息。
我們在項目的 common/enum 目錄中新增rediskey.go 在其中對Redis 緩存的 Key 進行統(tǒng)一管理
/ Redis Key的格式為:
// 項目名:模塊名:鍵名
const (
REDIS_KEY_DEMO_ORDER_DETAIL = "GOMALL:DEMO:ORDER_DETAIL_%s"
)
這里先定義一個測試用的Redis緩存的鍵名。
- GOMALL:DEMO:ORDER_DETAIL_%s
Key的格式為 項目名:模塊名:鍵名,你的公司大的話還可以在最前面加一個業(yè)務名,免得項目名重復了。
項目名:GOMALL
模塊名:DEMO (因為是演示,正常情況下是ORDER、USER 這種模塊名)
鍵名:ORDER_DETAIL_%s
在使用到這個 Redis 緩存的方法中可以來拿業(yè)務標識(比如訂單號) 拼裝出完整的Redis Key
redisKey := fmt.Sprintf(enum.REDIS_KEY_DEMO_ORDER_DETAIL, demoOrder.OrderNo)
Redis怎么做日志鏈路追蹤
和在項目中集成ORM使用數據庫時一樣,除了關注常規(guī)的功能外,我們還要關注組件集成進項目后的可觀測性。最基礎的保障觀測性的方式是組件日志整合到應用日志,并且通過traceId、reqeustId等方式講它們歸因到對應的請求上。