mirror of
https://github.com/xxjwxc/public.git
synced 2025-12-24 11:51:49 +08:00
添加redis 支持
This commit is contained in:
7
.vscode/launch.json
vendored
Normal file
7
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": []
|
||||
}
|
||||
@@ -5,5 +5,5 @@ golang 工具包。
|
||||
|
||||
包括:
|
||||
|
||||
`文件功能`,`leveldb`,`restful风格消息包头定义`,`cache缓存`,`绘图函数`,`elastic`,`echarts`,`http`,`日志`,`nsq抽取`,`线程安全队列`,`签名`,`gorm封装`,`时间函数`,`国际化i18n`,`gocui 界面类`,`驼峰命名转换工具`,`大驼峰到网络标准json串自动转换`,`剪切板`,`微信`,`ast`,`swagger 文档支持`,`mindoc/markdown 文档支持`,`分布式全局唯一id(myglobal)`,`ssh(支持tab自动补全)`,`zap logger`,`快递鸟`
|
||||
`文件功能`,`leveldb`,`restful风格消息包头定义`,`cache缓存`,`绘图函数`,`elastic`,`echarts`,`http`,`日志`,`nsq抽取`,`线程安全队列`,`签名`,`gorm封装`,`时间函数`,`国际化i18n`,`gocui 界面类`,`驼峰命名转换工具`,`大驼峰到网络标准json串自动转换`,`剪切板`,`微信`,`ast`,`swagger 文档支持`,`mindoc/markdown 文档支持`,`分布式全局唯一id(myglobal)`,`ssh(支持tab自动补全)`,`zap logger`,`快递鸟`,`redis`
|
||||
......
|
||||
|
||||
3
go.mod
3
go.mod
@@ -13,7 +13,7 @@ require (
|
||||
github.com/go-redis/redis/v8 v8.4.11
|
||||
github.com/go-sql-driver/mysql v1.5.0
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
|
||||
github.com/gomodule/redigo v1.8.3 // indirect
|
||||
github.com/gomodule/redigo v1.8.3
|
||||
github.com/gookit/color v1.2.5
|
||||
github.com/jander/golog v0.0.0-20150917071935-954a5be801fc
|
||||
github.com/jinzhu/gorm v1.9.12
|
||||
@@ -28,6 +28,7 @@ require (
|
||||
github.com/nsqio/go-nsq v1.0.8
|
||||
github.com/olivere/elastic v6.2.31+incompatible
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/prometheus/common v0.4.0
|
||||
github.com/spf13/cobra v1.0.0
|
||||
github.com/syndtr/goleveldb v1.0.0
|
||||
github.com/xxjwxc/gowp v0.0.0-20200603130651-4d7368b0e285
|
||||
|
||||
7
go.sum
7
go.sum
@@ -8,7 +8,9 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
||||
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc h1:cAKDfWh5VpdgMhJosfJnn5/FoN2SRZ4p7fJNX58YPaU=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf h1:qet1QNfXsQxTZqLG4oE62mJzwPIB8+Tee4RNCL9ulrY=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/ant0ine/go-json-rest v3.3.2+incompatible h1:nBixrkLFiDNAW0hauKDLc8yJI6XfrQumWvytE1Hk14E=
|
||||
github.com/ant0ine/go-json-rest v3.3.2+incompatible/go.mod h1:q6aCt0GfU6LhpBsnZ/2U+mwe+0XB5WStbmwyoPfc+sk=
|
||||
@@ -146,6 +148,7 @@ github.com/kardianos/service v1.0.0 h1:HgQS3mFfOlyntWX8Oke98JcJLqt1DBcHR4kxShpYe
|
||||
github.com/kardianos/service v1.0.0/go.mod h1:8CzDhVuCuugtsHyZoTvsOBuvonN/UDBvl0kH+BUxvbo=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
@@ -207,6 +210,7 @@ github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.4.0 h1:7etb9YClo3a6HjLzfl6rIQaU+FDfi0VSX39io3aQ+DM=
|
||||
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
@@ -217,6 +221,7 @@ github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6So
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.2.0 h1:juTguoYk5qI21pwyTXY3B3Y5cOTH3ZUyZCg1v/mihuo=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
@@ -318,6 +323,7 @@ golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@@ -352,6 +358,7 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
||||
@@ -7,9 +7,13 @@ import (
|
||||
"github.com/gomodule/redigo/redis"
|
||||
)
|
||||
|
||||
const KeepTTL = -1
|
||||
|
||||
// MyRedis redis配置项
|
||||
type MyRedis struct {
|
||||
conf *redisOptions
|
||||
con redis.Conn
|
||||
pool *redis.Pool
|
||||
mtx sync.Mutex
|
||||
once sync.Once
|
||||
dial RedisDial
|
||||
@@ -20,11 +24,12 @@ var _default = &MyRedis{}
|
||||
|
||||
// redisOption redisOption
|
||||
type redisOptions struct {
|
||||
con redis.Conn
|
||||
timeout time.Duration
|
||||
groupName string
|
||||
pwd string
|
||||
clientName string
|
||||
addrs []string
|
||||
addrIdex int
|
||||
db int
|
||||
readTimeout time.Duration
|
||||
writeTimeout time.Duration
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
package myredis
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func Test_cache(t *testing.T) {
|
||||
//获取
|
||||
res, _ := NewRedis([]string{"192.155.1.150:6379"}, "Niren1015", "gggg", 0)
|
||||
|
||||
fmt.Println(res.Clear())
|
||||
|
||||
aaa := "ccccc"
|
||||
res.Add("aaaa", aaa, 20*time.Second)
|
||||
res.Add("bbbb", aaa, 0)
|
||||
fmt.Println(res.Delete("aaaa"))
|
||||
|
||||
fmt.Print(res.IsExist("aaaa"))
|
||||
|
||||
var tt string
|
||||
res.Value("aaaa", &tt)
|
||||
|
||||
time.Sleep(20 * time.Second)
|
||||
fmt.Print(res.IsExist("aaaa"))
|
||||
|
||||
fmt.Println(res.Clear())
|
||||
|
||||
fmt.Println(tt)
|
||||
return
|
||||
}
|
||||
@@ -1,9 +1,23 @@
|
||||
package myredis
|
||||
|
||||
import "github.com/gomodule/redigo/redis"
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/gomodule/redigo/redis"
|
||||
)
|
||||
|
||||
// RedisDial 操作
|
||||
type RedisDial interface {
|
||||
Destory() // 析构
|
||||
GetRedisClient() redis.Conn // 获取一个原始的redis连接
|
||||
Ping() bool // 判断是否能ping通
|
||||
Add(key interface{}, value interface{}, lifeSpan time.Duration) error // 添加一个元素
|
||||
Value(key interface{}, value interface{}) error // 获取一个value
|
||||
IsExist(key interface{}) bool // 判断是否存在
|
||||
Delete(key interface{}) error // 删除一个
|
||||
Clear() error // 清空
|
||||
GetKeyS(key interface{}) ([]string, error) // 查询所有key
|
||||
Close() (err error) // 关闭连接
|
||||
}
|
||||
|
||||
// DefaultConf ...
|
||||
@@ -15,7 +29,7 @@ func DefaultConf() *MyRedis {
|
||||
}
|
||||
|
||||
// InitDefaultRedis 初始化(必须要优先调用一次)
|
||||
func InitDefaultRedis(ops ...Option) {
|
||||
func InitDefaultRedis(ops ...Option) *MyRedis {
|
||||
var tmp = &redisOptions{}
|
||||
for _, o := range ops {
|
||||
o.apply(tmp)
|
||||
@@ -27,6 +41,7 @@ func InitDefaultRedis(ops ...Option) {
|
||||
_default.mtx.Lock()
|
||||
defer _default.mtx.Unlock()
|
||||
_default.conf = tmp
|
||||
return _default
|
||||
}
|
||||
|
||||
// InitRedis 初始化(必须要优先调用一次)
|
||||
@@ -54,20 +69,28 @@ func NewRedis(con *MyRedis) (dial RedisDial, err error) {
|
||||
con.once.Do(func() { // 创建连接
|
||||
ReDialRedis(con)
|
||||
})
|
||||
|
||||
return nil, nil
|
||||
|
||||
return con.dial, nil
|
||||
}
|
||||
|
||||
// ReDialRedis 重新连接redis
|
||||
func ReDialRedis(con *MyRedis) {
|
||||
if con.dial != nil { // 清理,关闭连接
|
||||
con.dial.Destory()
|
||||
}
|
||||
|
||||
con.mtx.Lock()
|
||||
defer con.mtx.Unlock()
|
||||
if con.conf.maxIdle > 0 { // 创建连接池
|
||||
|
||||
if con.conf.maxIdle > 0 { // 创建连接池
|
||||
con.dial = &redisConPool{
|
||||
base: base{MyRedis: con},
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
con.dial =
|
||||
// 创建单个连接
|
||||
redis.Dial("tcp",con.)
|
||||
con.dial = &redisConOlny{
|
||||
base: base{MyRedis: con},
|
||||
}
|
||||
}
|
||||
|
||||
44
myredis/myredis_test.go
Normal file
44
myredis/myredis_test.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package myredis
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func Test_cache(t *testing.T) {
|
||||
conf := InitRedis(WithAddr("192.155.1.150:6379"), WithClientName(""),
|
||||
// WithPool(2, 2),
|
||||
WithTimeout(10*time.Second), WithReadTimeout(10*time.Second), WithWriteTimeout(10*time.Second),
|
||||
WithPwd("Niren1015"), WithGroupName("gggg"), WithDB(0))
|
||||
//获取
|
||||
res, err := NewRedis(conf)
|
||||
|
||||
fmt.Println(err)
|
||||
aaa := "ccccc"
|
||||
res.Add("aaaa", aaa, 20*time.Second)
|
||||
res.Add("bbbb", aaa, 0)
|
||||
res.Close()
|
||||
fmt.Println(res.Ping())
|
||||
|
||||
fmt.Print(res.IsExist("aaaa"))
|
||||
fmt.Print(res.GetKeyS("*"))
|
||||
fmt.Println(res.Clear())
|
||||
|
||||
fmt.Println(res.Delete("aaaa"))
|
||||
|
||||
var tt string
|
||||
res.Value("bbbb", &tt)
|
||||
|
||||
var ww []int32
|
||||
res.Add("cccc", []int32{1, 2, 3, 4}, 0)
|
||||
res.Value("cccc", &ww)
|
||||
|
||||
// time.Sleep(20 * time.Second)
|
||||
// fmt.Print(res.IsExist("aaaa"))
|
||||
|
||||
// fmt.Println(res.Clear())
|
||||
|
||||
// fmt.Println(tt)
|
||||
return
|
||||
}
|
||||
@@ -60,3 +60,10 @@ func WithPool(maxIdle, maxActive int) Option {
|
||||
o.maxActive = maxActive
|
||||
})
|
||||
}
|
||||
|
||||
// WithClientName 指定Redis服务器连接使用的客户端名称
|
||||
func WithClientName(name string) Option {
|
||||
return optionFunc(func(o *redisOptions) {
|
||||
o.clientName = name
|
||||
})
|
||||
}
|
||||
|
||||
166
myredis/pool.go
166
myredis/pool.go
@@ -1 +1,167 @@
|
||||
package myredis
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/gomodule/redigo/redis"
|
||||
"github.com/xxjwxc/public/mylog"
|
||||
)
|
||||
|
||||
type redisConPool struct {
|
||||
base
|
||||
}
|
||||
|
||||
func (mc *redisConPool) Destory() {
|
||||
mc.mtx.Lock()
|
||||
defer mc.mtx.Unlock()
|
||||
|
||||
if mc.con != nil {
|
||||
err := mc.con.Close()
|
||||
if err != nil {
|
||||
mylog.Error(err)
|
||||
}
|
||||
mc.con = nil
|
||||
}
|
||||
}
|
||||
|
||||
func (mc *redisConPool) GetRedisClient() redis.Conn {
|
||||
mc.mtx.Lock()
|
||||
defer mc.mtx.Unlock()
|
||||
if mc.pool == nil { // 创建连接
|
||||
mc.pool = &redis.Pool{
|
||||
MaxIdle: mc.conf.maxIdle,
|
||||
MaxActive: mc.conf.maxActive,
|
||||
Dial: func() (redis.Conn, error) {
|
||||
return mc.Dial()
|
||||
},
|
||||
TestOnBorrow: func(c redis.Conn, t time.Time) error {
|
||||
_, err := c.Do("PING")
|
||||
if err != nil {
|
||||
mylog.Errorf("ping redis error: %s", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
return mc.pool.Get()
|
||||
}
|
||||
|
||||
// Ping 判断是否能ping通
|
||||
func (mc *redisConPool) Ping() bool {
|
||||
return mc.ping(mc.GetRedisClient())
|
||||
}
|
||||
|
||||
// Add 添加一个缓存 lifeSpan:缓存时间,0表示永不超时
|
||||
func (mc *redisConPool) Add(key interface{}, value interface{}, lifeSpan time.Duration) error {
|
||||
var args []interface{}
|
||||
args = append(args, mc.getKey(key), mc.encodeValue(value))
|
||||
if lifeSpan > 0 {
|
||||
if usePrecise(lifeSpan) {
|
||||
args = append(args, "px", formatMs(lifeSpan))
|
||||
} else {
|
||||
args = append(args, "ex", formatSec(lifeSpan))
|
||||
}
|
||||
} else if lifeSpan == KeepTTL {
|
||||
args = append(args, "keepttl")
|
||||
}
|
||||
|
||||
repy, err := mc.Do(mc.GetRedisClient(), "SET", args...)
|
||||
mylog.Info(redis.String(repy, err))
|
||||
if err != nil {
|
||||
mylog.Error(err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Value 查找一个cache
|
||||
func (mc *redisConPool) Value(key interface{}, value interface{}) (err error) {
|
||||
repy, err := mc.Do(mc.GetRedisClient(), "GET", mc.getKey(key))
|
||||
if err != nil {
|
||||
mylog.Error(err)
|
||||
return err
|
||||
}
|
||||
return mc.decodeValue(repy, value)
|
||||
}
|
||||
|
||||
// IsExist 判断key是否存在
|
||||
func (mc *redisConPool) IsExist(key interface{}) bool {
|
||||
repy, err := mc.Do(mc.GetRedisClient(), "EXISTS", mc.getKey(key))
|
||||
if err != nil {
|
||||
mylog.Error(err)
|
||||
return false
|
||||
}
|
||||
exist, err := redis.Bool(repy, err) // 转化bool格式
|
||||
if err != nil {
|
||||
mylog.Error(err)
|
||||
return false
|
||||
}
|
||||
|
||||
return exist
|
||||
}
|
||||
|
||||
// Delete 删除一个cache
|
||||
func (mc *redisConPool) Delete(key interface{}) error {
|
||||
_, err := mc.Do(mc.GetRedisClient(), "del", mc.getKey(key))
|
||||
if err != nil {
|
||||
mylog.Error(err)
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Clear 清空表內容
|
||||
func (mc *redisConPool) Clear() error {
|
||||
out, err := mc.GetKeyS("*")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, v := range out {
|
||||
err = mc.Delete(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// GetKeyS 查询所有key
|
||||
func (mc *redisConPool) GetKeyS(key interface{}) ([]string, error) {
|
||||
var keys []string
|
||||
repy, err := mc.Do(mc.GetRedisClient(), "keys", mc.getKey(key))
|
||||
if err != nil {
|
||||
mylog.Error(err)
|
||||
return keys, err
|
||||
}
|
||||
|
||||
switch t := repy.(type) {
|
||||
case []interface{}:
|
||||
for _, v := range t {
|
||||
out, err := redis.String(v, nil)
|
||||
if err != nil {
|
||||
mylog.Error(err)
|
||||
}
|
||||
keys = append(keys, mc.fixKeyGroupName(out))
|
||||
}
|
||||
default:
|
||||
return keys, fmt.Errorf("decodeValue err in type not find:%v", t)
|
||||
}
|
||||
|
||||
return keys, err
|
||||
}
|
||||
|
||||
// Close 关闭一个连接
|
||||
func (mc *redisConPool) Close() (err error) {
|
||||
mc.mtx.Lock()
|
||||
defer mc.mtx.Unlock()
|
||||
if mc.con != nil {
|
||||
err = mc.con.Close()
|
||||
mc.con = nil
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -3,9 +3,13 @@ package myredis
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gomodule/redigo/redis"
|
||||
"github.com/prometheus/common/log"
|
||||
"github.com/xxjwxc/public/dev"
|
||||
"github.com/xxjwxc/public/mylog"
|
||||
"github.com/xxjwxc/public/tools"
|
||||
)
|
||||
@@ -19,157 +23,346 @@ func (mc *base) getCtx() context.Context {
|
||||
}
|
||||
|
||||
func (mc *base) getKey(key interface{}) string {
|
||||
tmp := ""
|
||||
if len(mc.conf.groupName) > 0 {
|
||||
return fmt.Sprintf("%v:%v", mc.conf.groupName, tools.JSONDecode(key))
|
||||
tmp = fmt.Sprintf("%v:", mc.conf.groupName)
|
||||
}
|
||||
switch t := key.(type) {
|
||||
case []byte:
|
||||
return fmt.Sprintf("%v%v", tmp, string(t))
|
||||
case string:
|
||||
return fmt.Sprintf("%v%v", tmp, t)
|
||||
default:
|
||||
return fmt.Sprintf("%v%v", tmp, tools.JSONDecode(key))
|
||||
}
|
||||
return tools.JSONDecode(key)
|
||||
}
|
||||
|
||||
func initConOlny(cnf *MyRedis) *redisConOlny {
|
||||
return &redisConOlny{
|
||||
base: base{MyRedis: cnf},
|
||||
func (mc *base) encodeValue(value interface{}) interface{} {
|
||||
switch t := value.(type) {
|
||||
case int32, byte, string, bool, int, uint, int8, int16, int64, uint16, uint32, uint64, float32, float64: // 基础类型
|
||||
return t
|
||||
default:
|
||||
return tools.JSONDecode(value)
|
||||
// data, _ := serializing.Encode(value)
|
||||
// return data
|
||||
}
|
||||
}
|
||||
|
||||
func (mc *base) decodeValue(in, out interface{}) (err error) {
|
||||
if in == nil {
|
||||
return fmt.Errorf("not fond")
|
||||
}
|
||||
|
||||
var reply string
|
||||
switch t := in.(type) {
|
||||
case []byte:
|
||||
reply = string(t)
|
||||
default:
|
||||
return fmt.Errorf("decodeValue err in type not find:%v", t)
|
||||
}
|
||||
|
||||
switch o := out.(type) {
|
||||
case *string: // string类型
|
||||
*o = reply
|
||||
return nil
|
||||
case *int32:
|
||||
i64, err := strconv.ParseInt(reply, 10, 0)
|
||||
*o = int32(i64)
|
||||
return err
|
||||
case *bool:
|
||||
b, err := strconv.ParseBool(string(reply))
|
||||
*o = b
|
||||
return err
|
||||
case *int:
|
||||
i64, err := strconv.ParseInt(reply, 10, 0)
|
||||
*o = int(i64)
|
||||
return err
|
||||
case *int8:
|
||||
i64, err := strconv.ParseInt(reply, 10, 0)
|
||||
*o = int8(i64)
|
||||
return err
|
||||
case *int16:
|
||||
i64, err := strconv.ParseInt(reply, 10, 0)
|
||||
*o = int16(i64)
|
||||
return err
|
||||
case *int64:
|
||||
i64, err := strconv.ParseInt(string(reply), 10, 64)
|
||||
*o = int64(i64)
|
||||
return err
|
||||
case *uint:
|
||||
i64, err := strconv.ParseUint(reply, 10, 0)
|
||||
*o = uint(i64)
|
||||
return err
|
||||
case *uint8:
|
||||
i64, err := strconv.ParseUint(reply, 10, 0)
|
||||
*o = uint8(i64)
|
||||
return err
|
||||
case *uint16:
|
||||
i64, err := strconv.ParseUint(reply, 10, 0)
|
||||
*o = uint16(i64)
|
||||
return err
|
||||
case *uint32:
|
||||
i64, err := strconv.ParseInt(string(reply), 10, 0)
|
||||
*o = uint32(i64)
|
||||
return err
|
||||
case *uint64:
|
||||
i64, err := strconv.ParseUint(reply, 10, 64)
|
||||
*o = uint64(i64)
|
||||
return err
|
||||
case *float32:
|
||||
f64, err := strconv.ParseFloat(string(reply), 32)
|
||||
*o = float32(f64)
|
||||
return err
|
||||
case *float64: // 基础类型
|
||||
f64, err := strconv.ParseFloat(string(reply), 64)
|
||||
*o = float64(f64)
|
||||
return err
|
||||
default:
|
||||
tools.JSONEncode(reply, out) // 复杂类型
|
||||
return nil
|
||||
//return serializing.Decode(t, out)
|
||||
|
||||
}
|
||||
|
||||
// return fmt.Errorf("decodeValue err not match:%v %v", in, out)
|
||||
}
|
||||
|
||||
func (mc *base) ping(con redis.Conn) bool {
|
||||
if con == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
_, err := con.Do("PING")
|
||||
if err != nil {
|
||||
mylog.Errorf("ping redis error: %s", err)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Dial 获取一个链接
|
||||
func (mc *base) Dial() (redis.Conn, error) {
|
||||
mc.mtx.Lock()
|
||||
defer mc.mtx.Unlock()
|
||||
if mc.con == nil { // 创建连接
|
||||
index := mc.conf.addrIdex
|
||||
len := len(mc.conf.addrs)
|
||||
b := false
|
||||
var err error
|
||||
for i := 0; i < len; i++ {
|
||||
index = (mc.conf.addrIdex + i) % len
|
||||
mc.con, err = redis.Dial("tcp", mc.conf.addrs[index], redis.DialClientName(mc.conf.clientName),
|
||||
redis.DialConnectTimeout(mc.conf.timeout), redis.DialDatabase(mc.conf.db),
|
||||
redis.DialPassword(mc.conf.pwd), redis.DialReadTimeout(mc.conf.readTimeout), redis.DialWriteTimeout(mc.conf.writeTimeout),
|
||||
)
|
||||
if err != nil {
|
||||
mylog.Error(err)
|
||||
}
|
||||
if mc.ping(mc.con) {
|
||||
b = true
|
||||
}
|
||||
}
|
||||
if b {
|
||||
mc.conf.addrIdex = (index + 1) % len
|
||||
}
|
||||
return mc.con, err
|
||||
}
|
||||
|
||||
return mc.con, nil
|
||||
}
|
||||
|
||||
func (mc *base) Do(con redis.Conn, commandName string, args ...interface{}) (reply interface{}, err error) {
|
||||
if dev.IsDev() {
|
||||
cmd := commandName
|
||||
for _, v := range args {
|
||||
cmd += fmt.Sprintf(" %v", v)
|
||||
}
|
||||
log.Infof("redis req :%v", cmd)
|
||||
}
|
||||
|
||||
if con != nil {
|
||||
reply, err = con.Do(commandName, args...)
|
||||
// show log
|
||||
if dev.IsDev() {
|
||||
tmp := ""
|
||||
switch reply := reply.(type) {
|
||||
case []byte:
|
||||
tmp = string(reply)
|
||||
case string:
|
||||
tmp = reply
|
||||
case int64:
|
||||
tmp = fmt.Sprintf("%v", reply)
|
||||
}
|
||||
log.Infof("redis resp:%v,%v", tmp, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
return nil, fmt.Errorf("con is nil")
|
||||
}
|
||||
|
||||
func (mc *base) fixKeyGroupName(key string) string {
|
||||
tmp := ""
|
||||
if len(mc.conf.groupName) > 0 {
|
||||
tmp = fmt.Sprintf("%v:", mc.conf.groupName)
|
||||
}
|
||||
return strings.TrimPrefix(key, tmp)
|
||||
}
|
||||
|
||||
type redisConOlny struct {
|
||||
base
|
||||
}
|
||||
|
||||
// NewRedis 初始化一个cache cachename 缓存名字
|
||||
func NewRedis(addrs []string, pwd, groupName string, timeout time.Duration) (mc *MyRedis, err error) {
|
||||
redis.Dial()
|
||||
redis.SetLogger(&logger{})
|
||||
if len(addrs) <= 1 {
|
||||
mc = &MyRedis{
|
||||
Cmdable: redis.NewClient(&redis.Options{
|
||||
Addr: addrs[0],
|
||||
DialTimeout: timeout,
|
||||
Password: pwd, // no password set
|
||||
// DB: 0, // use default DB
|
||||
}),
|
||||
}
|
||||
} else {
|
||||
mc = &MyRedis{
|
||||
Cmdable: redis.NewClusterClient(&redis.ClusterOptions{
|
||||
Addrs: addrs,
|
||||
Password: pwd, // no password set
|
||||
DialTimeout: timeout,
|
||||
}),
|
||||
// Destory 析构
|
||||
func (mc *redisConOlny) Destory() {
|
||||
mc.mtx.Lock()
|
||||
defer mc.mtx.Unlock()
|
||||
|
||||
if mc.con != nil {
|
||||
err := mc.con.Close()
|
||||
if err != nil {
|
||||
mylog.Error(err)
|
||||
}
|
||||
mc.con = nil
|
||||
}
|
||||
mc.timeout = timeout
|
||||
mc.groupName = groupName
|
||||
|
||||
err = mc.Ping(mc.getCtx()).Err()
|
||||
if err != nil {
|
||||
mylog.Error(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (mc *MyRedis) getCtx() context.Context {
|
||||
return context.Background()
|
||||
// GetRedisClient ...
|
||||
func (mc *redisConOlny) GetRedisClient() redis.Conn {
|
||||
con, _ := mc.Dial()
|
||||
return con
|
||||
}
|
||||
|
||||
func (mc *MyRedis) getKey(key interface{}) string {
|
||||
if len(mc.groupName) > 0 {
|
||||
return fmt.Sprintf("%v:%v", mc.groupName, tools.JSONDecode(key))
|
||||
}
|
||||
return tools.JSONDecode(key)
|
||||
// Ping 判断是否能ping通
|
||||
func (mc *redisConOlny) Ping() bool {
|
||||
return mc.ping(mc.GetRedisClient())
|
||||
}
|
||||
|
||||
// 判断是否能ping通
|
||||
// Add 添加一个缓存 lifeSpan:缓存时间,0表示永不超时
|
||||
func (mc *MyRedis) Add(key interface{}, value interface{}, lifeSpan time.Duration) (err error) {
|
||||
set := mc.Set(mc.getCtx(), mc.getKey(key), tools.JSONDecode(value), lifeSpan)
|
||||
mylog.Info(set.Val())
|
||||
// redis.Expect(set.Err()).NotTo(HaveOccurred())
|
||||
// redis.Expect(set.Val()).To(Equal("OK"))
|
||||
err = set.Err()
|
||||
func (mc *redisConOlny) Add(key interface{}, value interface{}, lifeSpan time.Duration) error {
|
||||
var args []interface{}
|
||||
args = append(args, mc.getKey(key), mc.encodeValue(value))
|
||||
if lifeSpan > 0 {
|
||||
if usePrecise(lifeSpan) {
|
||||
args = append(args, "px", formatMs(lifeSpan))
|
||||
} else {
|
||||
args = append(args, "ex", formatSec(lifeSpan))
|
||||
}
|
||||
} else if lifeSpan == KeepTTL {
|
||||
args = append(args, "keepttl")
|
||||
}
|
||||
|
||||
_, err := mc.Do(mc.GetRedisClient(), "SET", args...)
|
||||
if err != nil {
|
||||
mylog.Error(err)
|
||||
}
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
// Value 查找一个cache
|
||||
func (mc *MyRedis) Value(key interface{}, value interface{}) (err error) {
|
||||
set := mc.Get(mc.getCtx(), mc.getKey(key))
|
||||
|
||||
mylog.Info(set.Val())
|
||||
// redis.Expect(set.Err()).NotTo(HaveOccurred())
|
||||
// redis.Expect(set.Val()).To(Equal("OK"))
|
||||
err = set.Err()
|
||||
func (mc *redisConOlny) Value(key interface{}, value interface{}) (err error) {
|
||||
repy, err := mc.Do(mc.GetRedisClient(), "GET", mc.getKey(key))
|
||||
if err != nil {
|
||||
mylog.Error(err)
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
tools.JSONEncode(set.Val(), value)
|
||||
return
|
||||
return mc.decodeValue(repy, value)
|
||||
}
|
||||
|
||||
// IsExist 判断key是否存在
|
||||
func (mc *MyRedis) IsExist(key interface{}) bool {
|
||||
set := mc.Exists(mc.getCtx(), mc.getKey(key))
|
||||
mylog.Info(set.Val())
|
||||
// redis.Expect(set.Err()).NotTo(HaveOccurred())
|
||||
// redis.Expect(set.Val()).To(Equal("OK"))
|
||||
err := set.Err()
|
||||
func (mc *redisConOlny) IsExist(key interface{}) bool {
|
||||
repy, err := mc.Do(mc.GetRedisClient(), "EXISTS", mc.getKey(key))
|
||||
if err != nil {
|
||||
mylog.Error(err)
|
||||
return false
|
||||
}
|
||||
exist, err := redis.Bool(repy, err) // 转化bool格式
|
||||
if err != nil {
|
||||
mylog.Error(err)
|
||||
return false
|
||||
}
|
||||
|
||||
return set.Val() == 1
|
||||
return exist
|
||||
}
|
||||
|
||||
// Delete 删除一个cache
|
||||
func (mc *MyRedis) Delete(key interface{}) error {
|
||||
set := mc.Del(mc.getCtx(), mc.getKey(key))
|
||||
mylog.Info(set.Val())
|
||||
// redis.Expect(set.Err()).NotTo(HaveOccurred())
|
||||
// redis.Expect(set.Val()).To(Equal("OK"))
|
||||
err := set.Err()
|
||||
func (mc *redisConOlny) Delete(key interface{}) error {
|
||||
_, err := mc.Do(mc.GetRedisClient(), "del", mc.getKey(key))
|
||||
if err != nil {
|
||||
mylog.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// GetRedisClient 获取原始cache2go操作类
|
||||
func (mc *MyRedis) GetRedisClient() redis.Cmdable {
|
||||
return mc
|
||||
}
|
||||
|
||||
// Clear 清空表內容
|
||||
func (mc *MyRedis) Clear() error {
|
||||
key := "*"
|
||||
if len(mc.groupName) > 0 {
|
||||
key = fmt.Sprintf("%v:*", mc.groupName)
|
||||
func (mc *redisConOlny) Clear() error {
|
||||
out, err := mc.GetKeyS("*")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
set := mc.Pipeline().Do(mc.getCtx(), "KEYS", key)
|
||||
mylog.Info(set.Val())
|
||||
// redis.Expect(set.Err()).NotTo(HaveOccurred())
|
||||
// redis.Expect(set.Val()).To(Equal("OK"))
|
||||
err := set.Err()
|
||||
if err != nil {
|
||||
mylog.Error(err)
|
||||
}
|
||||
|
||||
return mc.delete(key)
|
||||
}
|
||||
|
||||
// delete 删除一个cache
|
||||
func (mc *MyRedis) delete(key string) error {
|
||||
set := mc.Del(mc.getCtx(), key)
|
||||
mylog.Info(set.Val())
|
||||
// redis.Expect(set.Err()).NotTo(HaveOccurred())
|
||||
// redis.Expect(set.Val()).To(Equal("OK"))
|
||||
err := set.Err()
|
||||
if err != nil {
|
||||
mylog.Error(err)
|
||||
for _, v := range out {
|
||||
err = mc.Delete(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// GetKeyS 查询所有key
|
||||
func (mc *redisConOlny) GetKeyS(key interface{}) ([]string, error) {
|
||||
var keys []string
|
||||
repy, err := mc.Do(mc.GetRedisClient(), "keys", mc.getKey(key))
|
||||
if err != nil {
|
||||
mylog.Error(err)
|
||||
return keys, err
|
||||
}
|
||||
|
||||
switch t := repy.(type) {
|
||||
case []interface{}:
|
||||
for _, v := range t {
|
||||
out, err := redis.String(v, nil)
|
||||
if err != nil {
|
||||
mylog.Error(err)
|
||||
}
|
||||
keys = append(keys, mc.fixKeyGroupName(out))
|
||||
}
|
||||
default:
|
||||
return keys, fmt.Errorf("decodeValue err in type not find:%v", t)
|
||||
}
|
||||
|
||||
return keys, err
|
||||
}
|
||||
|
||||
// Close 关闭一个连接
|
||||
func (mc *redisConOlny) Close() (err error) {
|
||||
mc.mtx.Lock()
|
||||
defer mc.mtx.Unlock()
|
||||
if mc.con != nil {
|
||||
err = mc.con.Close()
|
||||
mc.con = nil
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func usePrecise(dur time.Duration) bool {
|
||||
return dur < time.Second || dur%time.Second != 0
|
||||
}
|
||||
|
||||
func formatMs(dur time.Duration) int64 {
|
||||
if dur > 0 && dur < time.Millisecond {
|
||||
return 1
|
||||
}
|
||||
return int64(dur / time.Millisecond)
|
||||
}
|
||||
|
||||
func formatSec(dur time.Duration) int64 {
|
||||
if dur > 0 && dur < time.Second {
|
||||
return 1
|
||||
}
|
||||
return int64(dur / time.Second)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user