hotime/cache/cache_redis.go
hoteas b755519fc6 feat(cache): 优化缓存系统并重构数据库连接管理
- 将Redis连接方式改为连接池模式,提升连接复用效率
- 修复缓存注释错误,统一标识数据库缓存逻辑
- 添加数据检索结果非空验证,避免空指针异常
- 在数据库操作中添加读写锁保护,确保并发安全性
- 实现数据库查询和执行操作的重试机制,增强稳定性
- 更新配置文件中的缓存和数据库设置,优化缓存策略
- 重构README文档,补充框架特性和性能测试数据
- 添加示例路由配置,完善快速入门指南
2026-01-22 04:36:52 +08:00

191 lines
3.6 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package cache
import (
. "code.hoteas.com/golang/hotime/common"
"github.com/garyburd/redigo/redis"
"strings"
"sync"
"time"
)
type CacheRedis struct {
TimeOut int64
DbSet bool
SessionSet bool
Host string
Pwd string
Port int64
pool *redis.Pool
tag int64
ContextBase
*Error
initOnce sync.Once
}
func (that *CacheRedis) GetError() *Error {
return that.Error
}
func (that *CacheRedis) SetError(err *Error) {
that.Error = err
}
// 唯一标志
func (that *CacheRedis) GetTag() int64 {
if that.tag == int64(0) {
that.tag = time.Now().UnixNano()
}
return that.tag
}
// initPool 初始化连接池(只执行一次)
func (that *CacheRedis) initPool() {
that.initOnce.Do(func() {
that.pool = &redis.Pool{
MaxIdle: 10, // 最大空闲连接数
MaxActive: 100, // 最大活跃连接数0表示无限制
IdleTimeout: 5 * time.Minute, // 空闲连接超时时间
Wait: true, // 当连接池耗尽时是否等待
Dial: func() (redis.Conn, error) {
conn, err := redis.Dial("tcp", that.Host+":"+ObjToStr(that.Port),
redis.DialConnectTimeout(5*time.Second),
redis.DialReadTimeout(3*time.Second),
redis.DialWriteTimeout(3*time.Second),
)
if err != nil {
return nil, err
}
if that.Pwd != "" {
if _, err := conn.Do("AUTH", that.Pwd); err != nil {
conn.Close()
return nil, err
}
}
return conn, nil
},
TestOnBorrow: func(c redis.Conn, t time.Time) error {
if time.Since(t) < time.Minute {
return nil
}
_, err := c.Do("PING")
return err
},
}
})
}
// getConn 从连接池获取连接
func (that *CacheRedis) getConn() redis.Conn {
that.initPool()
if that.pool == nil {
return nil
}
return that.pool.Get()
}
func (that *CacheRedis) del(key string) {
conn := that.getConn()
if conn == nil {
return
}
defer conn.Close()
del := strings.Index(key, "*")
if del != -1 {
val, err := redis.Strings(conn.Do("KEYS", key))
if err != nil {
that.Error.SetError(err)
return
}
if len(val) == 0 {
return
}
conn.Send("MULTI")
for i := range val {
conn.Send("DEL", val[i])
}
_, err = conn.Do("EXEC")
if err != nil {
that.Error.SetError(err)
}
} else {
_, err := conn.Do("DEL", key)
if err != nil {
that.Error.SetError(err)
}
}
}
// key value ,时间为时间戳
func (that *CacheRedis) set(key string, value string, expireSeconds int64) {
conn := that.getConn()
if conn == nil {
return
}
defer conn.Close()
_, err := conn.Do("SET", key, value, "EX", ObjToStr(expireSeconds))
if err != nil {
that.Error.SetError(err)
}
}
func (that *CacheRedis) get(key string) *Obj {
reData := &Obj{}
conn := that.getConn()
if conn == nil {
return reData
}
defer conn.Close()
var err error
reData.Data, err = redis.String(conn.Do("GET", key))
if err != nil {
reData.Data = nil
if !strings.Contains(err.Error(), "nil returned") {
that.Error.SetError(err)
}
}
return reData
}
func (that *CacheRedis) Cache(key string, data ...interface{}) *Obj {
reData := &Obj{}
//查询缓存
if len(data) == 0 {
reData = that.get(key)
return reData
}
tim := int64(0)
//删除缓存
if len(data) == 1 && data[0] == nil {
that.del(key)
return reData
}
//添加缓存
if len(data) == 1 {
if that.TimeOut == 0 {
//that.Time = Config.GetInt64("cacheShortTime")
}
tim += that.TimeOut
}
if len(data) == 2 {
that.Error.SetError(nil)
tempt := ObjToInt64(data[1], that.Error)
if tempt > tim {
tim = tempt
} else if that.GetError() == nil {
tim = tim + tempt
}
}
that.set(key, ObjToStr(data[0]), tim)
return reData
}