- 将Redis连接方式改为连接池模式,提升连接复用效率 - 修复缓存注释错误,统一标识数据库缓存逻辑 - 添加数据检索结果非空验证,避免空指针异常 - 在数据库操作中添加读写锁保护,确保并发安全性 - 实现数据库查询和执行操作的重试机制,增强稳定性 - 更新配置文件中的缓存和数据库设置,优化缓存策略 - 重构README文档,补充框架特性和性能测试数据 - 添加示例路由配置,完善快速入门指南
191 lines
3.6 KiB
Go
191 lines
3.6 KiB
Go
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
|
||
}
|