mirror of
https://github.com/lkmio/gb-cms.git
synced 2026-04-22 23:17:22 +08:00
346 lines
7.1 KiB
Go
346 lines
7.1 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"github.com/gomodule/redigo/redis"
|
|
)
|
|
|
|
type RedisUtils struct {
|
|
pool *redis.Pool
|
|
password string
|
|
}
|
|
|
|
func (utils *RedisUtils) CreateExecutor() (Executor, error) {
|
|
conn := utils.pool.Get()
|
|
if utils.password != "" {
|
|
if _, err := conn.Do("auth", utils.password); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
//if _, err := conn.Do("select", index); err != nil {
|
|
// return nil, err
|
|
//}
|
|
|
|
return &RedisExecutor{
|
|
conn: conn,
|
|
}, nil
|
|
}
|
|
|
|
type Executor interface {
|
|
DB(index int) Executor
|
|
|
|
Key(key string) Executor
|
|
|
|
Do(commandName string, args ...interface{}) (reply interface{}, err error)
|
|
|
|
// Keys 返回所有主键
|
|
Keys() ([]string, error)
|
|
|
|
Set(value interface{}) error
|
|
|
|
Get() (interface{}, error)
|
|
|
|
Exist() (bool, error)
|
|
|
|
Del() error
|
|
|
|
HSet(k string, v interface{}) error
|
|
|
|
HGet(k string) ([]byte, error)
|
|
|
|
HGetAll() (map[string][]byte, error)
|
|
|
|
HExist(k string) (bool, error)
|
|
|
|
HDel(k string) error
|
|
|
|
HSan(page, size int) ([][]string, error)
|
|
|
|
ZAdd(score interface{}, v interface{}) error
|
|
|
|
ZAddWithNotExists(score interface{}, v interface{}) error
|
|
|
|
// ZRangeWithDesc 降序查询
|
|
ZRangeWithDesc(page, size int) ([]string, error)
|
|
|
|
// ZRangeWithAsc 升序查询
|
|
ZRangeWithAsc(page, size int) ([]string, error)
|
|
|
|
// ZRange 返回zset所有元素
|
|
ZRange() ([][2]string, error)
|
|
|
|
ZGetScore(member interface{}) (interface{}, error)
|
|
|
|
ZDel(member interface{}) error
|
|
|
|
ZDelWithScore(score interface{}) error
|
|
|
|
// CountZSet 返回zset元素个数
|
|
CountZSet() (int, error)
|
|
|
|
SetExpires(expires int) error
|
|
}
|
|
|
|
type RedisExecutor struct {
|
|
conn redis.Conn
|
|
db int
|
|
key string
|
|
}
|
|
|
|
func (e *RedisExecutor) DB(index int) Executor {
|
|
e.db = index
|
|
return e
|
|
}
|
|
|
|
func (e *RedisExecutor) Key(key string) Executor {
|
|
e.key = key
|
|
return e
|
|
}
|
|
|
|
func (e *RedisExecutor) Do(commandName string, args ...interface{}) (interface{}, error) {
|
|
if _, err := e.conn.Do("select", e.db); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return e.conn.Do(commandName, args...)
|
|
}
|
|
|
|
func (e *RedisExecutor) Keys() ([]string, error) {
|
|
data, err := e.Do("keys", "*")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var keys []string
|
|
for _, key := range data.([]interface{}) {
|
|
keys = append(keys, string(key.([]uint8)))
|
|
}
|
|
|
|
return keys, nil
|
|
}
|
|
|
|
func (e *RedisExecutor) SetExpires(expires int) error {
|
|
_, err := e.Do("expire", e.key, expires)
|
|
return err
|
|
}
|
|
|
|
// HSet 设置map元素
|
|
func (e *RedisExecutor) HSet(entryK string, entryV interface{}) error {
|
|
_, err := e.Do("hset", e.key, entryK, entryV)
|
|
return err
|
|
}
|
|
|
|
func (e *RedisExecutor) Del() error {
|
|
_, err := e.Do("del", e.key)
|
|
return err
|
|
}
|
|
|
|
func (e *RedisExecutor) HDel(entryK string) error {
|
|
_, err := e.Do("del", e.key, entryK)
|
|
return err
|
|
}
|
|
|
|
func (e *RedisExecutor) Set(value interface{}) error {
|
|
_, err := e.Do("set", e.key, value)
|
|
return err
|
|
}
|
|
|
|
func (e *RedisExecutor) Get() (interface{}, error) {
|
|
return e.Do("get", e.key)
|
|
}
|
|
|
|
func (e *RedisExecutor) Exist() (bool, error) {
|
|
return redis.Bool(e.Do("exist", e.key))
|
|
}
|
|
|
|
func (e *RedisExecutor) HGet(k string) ([]byte, error) {
|
|
data, err := e.Do("hget", e.key, k)
|
|
if err != nil {
|
|
return nil, err
|
|
} else if data == nil {
|
|
return nil, nil
|
|
}
|
|
|
|
return data.([]byte), err
|
|
}
|
|
|
|
func (e *RedisExecutor) HGetAll() (map[string][]byte, error) {
|
|
data, err := e.Do("hgetall", e.key)
|
|
if err != nil {
|
|
return nil, err
|
|
} else if data == nil {
|
|
return nil, err
|
|
}
|
|
|
|
entries := data.([]interface{})
|
|
n := len(entries) / 2
|
|
result := make(map[string][]byte, n)
|
|
for i := 0; i < n; i++ {
|
|
result[string(entries[i*2].([]uint8))] = entries[i*2+1].([]uint8)
|
|
}
|
|
|
|
return result, err
|
|
}
|
|
|
|
func (e *RedisExecutor) HExist(k string) (bool, error) {
|
|
return redis.Bool(e.Do("exist", e.key, k))
|
|
}
|
|
|
|
func (e *RedisExecutor) HSan(page, size int) ([][]string, error) {
|
|
reply, err := e.Do("hscan", e.key, (page-1)*size, "count", size)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
response, _ := reply.([]interface{})
|
|
_ = response[0]
|
|
data := response[1].([]interface{})
|
|
|
|
n := len(data) / 2
|
|
var result [][]string
|
|
for i := 0; i < n; i++ {
|
|
pair := make([]string, 2)
|
|
pair[0] = string(data[i*2].([]uint8))
|
|
pair[1] = string(data[i*2+1].([]uint8))
|
|
result = append(result, pair)
|
|
}
|
|
|
|
return result, err
|
|
}
|
|
|
|
func (e *RedisExecutor) ZAdd(score interface{}, v interface{}) error {
|
|
_, err := e.Do("zadd", e.key, score, v)
|
|
return err
|
|
}
|
|
|
|
func (e *RedisExecutor) ZAddWithNotExists(score interface{}, v interface{}) error {
|
|
_, err := e.Do("zadd", e.key, "nx", score, v)
|
|
return err
|
|
}
|
|
|
|
func (e *RedisExecutor) ZRangeWithDesc(page, size int) ([]string, error) {
|
|
reply, err := e.Do("zrevrange", e.key, (page-1)*size, (page-1)*size+size-1)
|
|
data := reply.([]interface{})
|
|
|
|
var result []string
|
|
for _, v := range data {
|
|
result = append(result, string(v.([]uint8)))
|
|
}
|
|
|
|
return result, err
|
|
}
|
|
|
|
func (e *RedisExecutor) ZRangeWithAsc(page, size int) ([]string, error) {
|
|
reply, err := e.Do("zrange", e.key, (page-1)*size, (page-1)*size+size-1)
|
|
data := reply.([]interface{})
|
|
|
|
var result []string
|
|
for _, v := range data {
|
|
result = append(result, string(v.([]uint8)))
|
|
}
|
|
|
|
return result, err
|
|
}
|
|
|
|
func (e *RedisExecutor) ZDel(member interface{}) error {
|
|
_, err := e.Do("zrem", e.key, member)
|
|
return err
|
|
}
|
|
|
|
func (e *RedisExecutor) ZDelWithScore(score interface{}) error {
|
|
_, err := e.Do("zremrangebyscore", e.key, score, score)
|
|
return err
|
|
}
|
|
|
|
func (e *RedisExecutor) ZRange() ([][2]string, error) {
|
|
reply, err := e.Do("zrange", e.key, 0, -1, "withscores")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
data := reply.([]interface{})
|
|
n := len(data) / 2
|
|
|
|
var result [][2]string
|
|
for i := 0; i < n; i++ {
|
|
var pair [2]string
|
|
pair[0] = string(data[i*2].([]uint8))
|
|
pair[1] = string(data[i*2+1].([]uint8))
|
|
result = append(result, pair)
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
func (e *RedisExecutor) ZGetScore(member interface{}) (interface{}, error) {
|
|
return e.Do("zrank", e.key, member)
|
|
}
|
|
|
|
func (e *RedisExecutor) CountZSet() (int, error) {
|
|
do, err := e.Do("zcard", e.key)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
return int(do.(int64)), err
|
|
}
|
|
|
|
func StartExpiredKeysSubscription(utils *RedisUtils, db int, cb func(db int, key string)) error {
|
|
conn := utils.pool.Get()
|
|
|
|
if "" != utils.password {
|
|
if _, err := conn.Do("auth", utils.password); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
if _, err := conn.Do("config", "set", "protected-mode", "no"); err != nil {
|
|
return err
|
|
}
|
|
|
|
if _, err := conn.Do("config", "set", "notify-keyspace-events", "AE"); err != nil {
|
|
return err
|
|
}
|
|
|
|
redisClient := redis.PubSubConn{Conn: conn}
|
|
pattern := fmt.Sprintf("__keyevent@%d__:expired", db)
|
|
if err := redisClient.PSubscribe(pattern); err != nil {
|
|
return err
|
|
}
|
|
|
|
go func() {
|
|
for {
|
|
switch msg := redisClient.Receive().(type) {
|
|
case redis.Message:
|
|
if pattern == msg.Pattern {
|
|
key := string(msg.Data)
|
|
go cb(db, key)
|
|
}
|
|
break
|
|
case redis.Subscription:
|
|
break
|
|
case error:
|
|
break
|
|
}
|
|
}
|
|
}()
|
|
|
|
return nil
|
|
}
|
|
|
|
func NewRedisUtils(addr, password string) *RedisUtils {
|
|
return &RedisUtils{
|
|
pool: &redis.Pool{
|
|
MaxIdle: 50, // 最大空闲连接数
|
|
MaxActive: 0, // 和数据库的最大连接数,0 表示没有限制
|
|
IdleTimeout: 1000, // 最大空闲时间
|
|
Dial: func() (redis.Conn, error) { // 初始化连接的代码
|
|
return redis.Dial("tcp", addr)
|
|
},
|
|
},
|
|
|
|
password: password,
|
|
}
|
|
}
|