单例的使用
var redisClient redis.UniversalClient
var onceRedisClient = &sync.Once{}
var invokeTimes atomic.Int64 // redisClient被调用次数
// InitRedis 初始化redis客户端
// redisConnectionName redis连接名
func InitRedis(redisConnectionName string) {
onceRedisClient.Do(func() {
if len(redisConnectionName) == 0 {
log.Fatalf("db.InitRedis: no connection name while create redis client")
}
var err error = nil
redisClient, err = goredis.New(redisConnectionName)
if err != nil {
log.Fatalf("db.InitRedis: [%s]new redis client fail err=[%v]", redisConnectionName, err)
}
})
}
// GetRedis 获取redis客户端
func GetRedis() redis.UniversalClient {
if redisClient == nil {
log.Fatalf("db.GetRedis: redis client not inited")
return nil
}
if times := invokeTimes.Add(1); times%1000 == 0 {
log.Debugf("db.GetRedis: %v redis ConnPool Stats: %+v, invokeTimes: %v", &redisClient, redisClient.PoolStats(), times)
}
return redisClient
}
这是一段初始化redis的逻辑,因为我们无论是用数据库还是redis,都要链接redis的客户端,我们不可能使用一次方法就链接一次,所以正确方法就是这样的初始化,作为单例,然后建立连接池,然后我们调用GetRedis方法后单例就可以了
10.热加载怎么实现
// ActivityConf 活动配置
type ActivityConf struct {
SignKey string `yaml:"sign_key"`
ObWarmUpActivityOpen bool `yaml:"ob_warm_up_activity_open"`
}
var activityConf = ActivityConf{}
var activityLock sync.RWMutex
const defaultActivityConfigPath = "./conf/activity_cfg.yaml"
func init() {
// 创建文件监听器
fm, err := filemonitor.NewFileMonitor()
if err != nil {
log.Fatalf("Failed to NewFileMonitor: %v", err)
}
// Bind: 告诉程序 "你要盯着 ./conf/activity_cfg.yaml 这个文件"
// Exec: 程序启动时,立刻执行一次 loadActivityConfig,保证服务刚启动就有配置数据。
if err := fm.BindAndExec(defaultActivityConfigPath, loadActivityConfig); err != nil {
log.Fatalf("Failed to BindAndExec: %v", err)
}
// 3. 开启后台协程
// 这是一个死循环的后台任务,它利用操作系统的能力(如 Linux 的 inotify)
// 一旦发现文件被"保存/修改"了,它就会自动调用 loadActivityConfig
fm.StartWatch()
}
func loadActivityConfig() error {
// 1. 读文件 (IO 操作,很慢,不需要加锁)
// 此时还不涉及修改全局变量,所以不需要锁,别挡着读请求。
yamlFile, err := os.ReadFile(defaultActivityConfigPath)
if err != nil {
log.Fatalf("读取文件失败: %v", err)
return err
}
activityLock.Lock()
defer activityLock.Unlock()
// 这里直接修改了全局变量 activityConf 的内容,真正需要加锁的地方
err = yaml.Unmarshal(yamlFile, &activityConf)
if err != nil {
log.Fatalf("解析 YAML 失败: %v", err)
return err
}
log.Infof("Load tlog config: %+v", activityConf)
return nil
}
func GetActivityConf() ActivityConf {
activityLock.RLock()
defer activityLock.RUnlock()
return activityConf
}这是一段简单的读取配置文件的热加载模式,熟悉了这个方法就可以了。
评论