feat(cache): 优化缓存系统并重构数据库连接管理
- 将Redis连接方式改为连接池模式,提升连接复用效率 - 修复缓存注释错误,统一标识数据库缓存逻辑 - 添加数据检索结果非空验证,避免空指针异常 - 在数据库操作中添加读写锁保护,确保并发安全性 - 实现数据库查询和执行操作的重试机制,增强稳定性 - 更新配置文件中的缓存和数据库设置,优化缓存策略 - 重构README文档,补充框架特性和性能测试数据 - 添加示例路由配置,完善快速入门指南
This commit is contained in:
Vendored
+9
-9
@@ -1,8 +1,9 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
. "code.hoteas.com/golang/hotime/common"
|
||||
"errors"
|
||||
|
||||
. "code.hoteas.com/golang/hotime/common"
|
||||
)
|
||||
|
||||
// HoTimeCache 可配置memory,db,redis,默认启用memory,默认优先级为memory>redis>db,memory与数据库缓存设置项一致,
|
||||
@@ -92,7 +93,7 @@ func (that *HoTimeCache) Db(key string, data ...interface{}) *Obj {
|
||||
}
|
||||
}
|
||||
|
||||
//redis缓存有
|
||||
//db缓存有
|
||||
if that.dbCache != nil && that.dbCache.DbSet {
|
||||
reData = that.dbCache.Cache(key, data...)
|
||||
if reData.Data != nil {
|
||||
@@ -119,7 +120,7 @@ func (that *HoTimeCache) Db(key string, data ...interface{}) *Obj {
|
||||
if that.redisCache != nil && that.redisCache.DbSet {
|
||||
reData = that.redisCache.Cache(key, data...)
|
||||
}
|
||||
//redis缓存有
|
||||
//db缓存有
|
||||
if that.dbCache != nil && that.dbCache.DbSet {
|
||||
reData = that.dbCache.Cache(key, data...)
|
||||
}
|
||||
@@ -132,7 +133,7 @@ func (that *HoTimeCache) Cache(key string, data ...interface{}) *Obj {
|
||||
//内存缓存有
|
||||
if that.memoryCache != nil {
|
||||
reData = that.memoryCache.Cache(key, data...)
|
||||
if reData != nil {
|
||||
if reData != nil && reData.Data != nil {
|
||||
return reData
|
||||
}
|
||||
}
|
||||
@@ -140,8 +141,7 @@ func (that *HoTimeCache) Cache(key string, data ...interface{}) *Obj {
|
||||
//redis缓存有
|
||||
if that.redisCache != nil {
|
||||
reData = that.redisCache.Cache(key, data...)
|
||||
if reData.Data != nil {
|
||||
|
||||
if reData != nil && reData.Data != nil {
|
||||
if that.memoryCache != nil {
|
||||
that.memoryCache.Cache(key, reData.Data)
|
||||
}
|
||||
@@ -149,10 +149,10 @@ func (that *HoTimeCache) Cache(key string, data ...interface{}) *Obj {
|
||||
}
|
||||
}
|
||||
|
||||
//redis缓存有
|
||||
//db缓存有
|
||||
if that.dbCache != nil {
|
||||
reData = that.dbCache.Cache(key, data...)
|
||||
if reData.Data != nil {
|
||||
if reData != nil && reData.Data != nil {
|
||||
if that.memoryCache != nil {
|
||||
that.memoryCache.Cache(key, reData.Data)
|
||||
}
|
||||
@@ -174,7 +174,7 @@ func (that *HoTimeCache) Cache(key string, data ...interface{}) *Obj {
|
||||
if that.redisCache != nil {
|
||||
reData = that.redisCache.Cache(key, data...)
|
||||
}
|
||||
//redis缓存有
|
||||
//db缓存有
|
||||
if that.dbCache != nil {
|
||||
reData = that.dbCache.Cache(key, data...)
|
||||
}
|
||||
|
||||
Vendored
+87
-67
@@ -4,6 +4,7 @@ import (
|
||||
. "code.hoteas.com/golang/hotime/common"
|
||||
"github.com/garyburd/redigo/redis"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -14,10 +15,11 @@ type CacheRedis struct {
|
||||
Host string
|
||||
Pwd string
|
||||
Port int64
|
||||
conn redis.Conn
|
||||
pool *redis.Pool
|
||||
tag int64
|
||||
ContextBase
|
||||
*Error
|
||||
initOnce sync.Once
|
||||
}
|
||||
|
||||
func (that *CacheRedis) GetError() *Error {
|
||||
@@ -39,83 +41,112 @@ func (that *CacheRedis) GetTag() int64 {
|
||||
return that.tag
|
||||
}
|
||||
|
||||
func (that *CacheRedis) reCon() bool {
|
||||
var err error
|
||||
that.conn, err = redis.Dial("tcp", that.Host+":"+ObjToStr(that.Port))
|
||||
if err != nil {
|
||||
that.conn = nil
|
||||
that.Error.SetError(err)
|
||||
return false
|
||||
}
|
||||
|
||||
if that.Pwd != "" {
|
||||
_, err = that.conn.Do("AUTH", that.Pwd)
|
||||
if err != nil {
|
||||
that.conn = nil
|
||||
that.Error.SetError(err)
|
||||
return false
|
||||
// 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
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
// 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(that.conn.Do("KEYS", key))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
that.conn.Send("MULTI")
|
||||
for i, _ := range val {
|
||||
that.conn.Send("DEL", val[i])
|
||||
}
|
||||
that.conn.Do("EXEC")
|
||||
} else {
|
||||
_, err := that.conn.Do("DEL", key)
|
||||
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)
|
||||
_, err = that.conn.Do("PING")
|
||||
if err != nil {
|
||||
if that.reCon() {
|
||||
_, err = that.conn.Do("DEL", key)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// key value ,时间为时间戳
|
||||
func (that *CacheRedis) set(key string, value string, time int64) {
|
||||
_, err := that.conn.Do("SET", key, value, "EX", ObjToStr(time))
|
||||
if err != nil {
|
||||
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)
|
||||
_, err = that.conn.Do("PING")
|
||||
if err != nil {
|
||||
if that.reCon() {
|
||||
_, err = that.conn.Do("SET", key, value, "EX", ObjToStr(time))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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(that.conn.Do("GET", key))
|
||||
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)
|
||||
_, err = that.conn.Do("PING")
|
||||
if err != nil {
|
||||
if that.reCon() {
|
||||
reData.Data, err = redis.String(that.conn.Do("GET", key))
|
||||
}
|
||||
}
|
||||
|
||||
return reData
|
||||
}
|
||||
}
|
||||
return reData
|
||||
@@ -123,19 +154,13 @@ func (that *CacheRedis) get(key string) *Obj {
|
||||
|
||||
func (that *CacheRedis) Cache(key string, data ...interface{}) *Obj {
|
||||
reData := &Obj{}
|
||||
if that.conn == nil {
|
||||
re := that.reCon()
|
||||
if !re {
|
||||
return reData
|
||||
}
|
||||
}
|
||||
|
||||
//查询缓存
|
||||
if len(data) == 0 {
|
||||
|
||||
reData = that.get(key)
|
||||
return reData
|
||||
|
||||
}
|
||||
|
||||
tim := int64(0)
|
||||
//删除缓存
|
||||
if len(data) == 1 && data[0] == nil {
|
||||
@@ -144,21 +169,17 @@ func (that *CacheRedis) Cache(key string, data ...interface{}) *Obj {
|
||||
}
|
||||
//添加缓存
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -166,5 +187,4 @@ func (that *CacheRedis) Cache(key string, data ...interface{}) *Obj {
|
||||
that.set(key, ObjToStr(data[0]), tim)
|
||||
|
||||
return reData
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user