feat加入redis工具包

This commit is contained in:
TsMask
2023-09-07 19:13:09 +08:00
parent 09c7b751fc
commit f1a0c9555b
5 changed files with 254 additions and 0 deletions

1
go.mod
View File

@@ -30,6 +30,7 @@ require (
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
xorm.io/xorm v1.3.2 xorm.io/xorm v1.3.2
github.com/redis/go-redis/v9 v9.1.0
) )
require ( require (

4
go.sum
View File

@@ -67,6 +67,8 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bsm/ginkgo/v2 v2.9.5 h1:rtVBYPs3+TC5iLUVOis1B9tjLTup7Cj5IfzosKtvTJ0=
github.com/bsm/gomega v1.26.0 h1:LhQm+AFcgV2M0WyKroMASzAzCAJVpAxQXv4SaI9a69Y=
github.com/bsm/redislock v0.8.2 h1:W0aDRjt6FNmAZovbG2fPyjl1YZZdlqMkCKKCffJew1o= github.com/bsm/redislock v0.8.2 h1:W0aDRjt6FNmAZovbG2fPyjl1YZZdlqMkCKKCffJew1o=
github.com/bsm/redislock v0.8.2/go.mod h1:tC0JZxZCdJN4DCB31cGxgjgf/ye1R4LLNJQd5ecjg08= github.com/bsm/redislock v0.8.2/go.mod h1:tC0JZxZCdJN4DCB31cGxgjgf/ye1R4LLNJQd5ecjg08=
github.com/bytedance/go-tagexpr/v2 v2.7.12 h1:qL2f0j11S8DHQsUWUA6aacLNBcbPTbNKuzVjaW4kF/M= github.com/bytedance/go-tagexpr/v2 v2.7.12 h1:qL2f0j11S8DHQsUWUA6aacLNBcbPTbNKuzVjaW4kF/M=
@@ -571,6 +573,8 @@ github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/redis/go-redis/v9 v9.1.0 h1:137FnGdk+EQdCbye1FW+qOEcY5S+SpY9T0NiuqvtfMY=
github.com/redis/go-redis/v9 v9.1.0/go.mod h1:urWj3He21Dj5k4TK1y59xH8Uj6ATueP8AH1cY3lZl4c=
github.com/reiver/go-oi v1.0.0 h1:nvECWD7LF+vOs8leNGV/ww+F2iZKf3EYjYZ527turzM= github.com/reiver/go-oi v1.0.0 h1:nvECWD7LF+vOs8leNGV/ww+F2iZKf3EYjYZ527turzM=
github.com/reiver/go-oi v1.0.0/go.mod h1:RrDBct90BAhoDTxB1fenZwfykqeGvhI6LsNfStJoEkI= github.com/reiver/go-oi v1.0.0/go.mod h1:RrDBct90BAhoDTxB1fenZwfykqeGvhI6LsNfStJoEkI=
github.com/reiver/go-telnet v0.0.0-20180421082511-9ff0b2ab096e h1:quuzZLi72kkJjl+f5AQ93FMcadG19WkS7MO6TXFOSas= github.com/reiver/go-telnet v0.0.0-20180421082511-9ff0b2ab096e h1:quuzZLi72kkJjl+f5AQ93FMcadG19WkS7MO6TXFOSas=

237
lib/core/redis/redis.go Normal file
View File

@@ -0,0 +1,237 @@
package redis
import (
"context"
"fmt"
"strings"
"time"
"ems.agt/lib/core/conf"
"ems.agt/lib/log"
"github.com/redis/go-redis/v9"
)
// Redis连接实例
var rdb *redis.Client
// 声明定义限流脚本命令
var rateLimitCommand = redis.NewScript(`
local key = KEYS[1]
local time = tonumber(ARGV[1])
local count = tonumber(ARGV[2])
local current = redis.call('get', key);
if current and tonumber(current) >= count then
return tonumber(current);
end
current = redis.call('incr', key)
if tonumber(current) == 1 then
redis.call('expire', key, time)
end
return tonumber(current);`)
// 连接Redis实例
func Connect() {
ctx := context.Background()
client := conf.Get("redis").(map[string]any)
address := fmt.Sprintf("%s:%d", client["host"], client["port"])
// 创建连接
rdb = redis.NewClient(&redis.Options{
Addr: address,
Password: client["password"].(string),
DB: client["db"].(int),
})
// 测试数据库连接
pong, err := rdb.Ping(ctx).Result()
if err != nil {
log.Fatalf("failed error ping redis: %v", err)
}
log.Infof("redis %s connection is successful.", pong)
}
// 关闭Redis实例
func Close() {
if err := rdb.Close(); err != nil {
log.Fatalf("fatal error db close: %s", err)
}
}
// Info 获取redis服务信息
func Info() map[string]map[string]string {
ctx := context.Background()
info, err := rdb.Info(ctx).Result()
if err != nil {
return map[string]map[string]string{}
}
infoObj := make(map[string]map[string]string)
lines := strings.Split(info, "\r\n")
label := ""
for _, line := range lines {
if strings.Contains(line, "#") {
label = strings.Fields(line)[len(strings.Fields(line))-1]
label = strings.ToLower(label)
infoObj[label] = make(map[string]string)
continue
}
kvArr := strings.Split(line, ":")
if len(kvArr) >= 2 {
key := strings.TrimSpace(kvArr[0])
value := strings.TrimSpace(kvArr[len(kvArr)-1])
infoObj[label][key] = value
}
}
return infoObj
}
// KeySize 获取redis当前连接可用键Key总数信息
func KeySize() int64 {
ctx := context.Background()
size, err := rdb.DBSize(ctx).Result()
if err != nil {
return 0
}
return size
}
// CommandStats 获取redis命令状态信息
func CommandStats() []map[string]string {
ctx := context.Background()
commandstats, err := rdb.Info(ctx, "commandstats").Result()
if err != nil {
return []map[string]string{}
}
statsObjArr := make([]map[string]string, 0)
lines := strings.Split(commandstats, "\r\n")
for _, line := range lines {
if !strings.HasPrefix(line, "cmdstat_") {
continue
}
kvArr := strings.Split(line, ":")
key := kvArr[0]
valueStr := kvArr[len(kvArr)-1]
statsObj := make(map[string]string)
statsObj["name"] = key[8:]
statsObj["value"] = valueStr[6:strings.Index(valueStr, ",usec=")]
statsObjArr = append(statsObjArr, statsObj)
}
return statsObjArr
}
// 获取键的剩余有效时间(秒)
func GetExpire(key string) float64 {
ctx := context.Background()
ttl, err := rdb.TTL(ctx, key).Result()
if err != nil {
return 0
}
return ttl.Seconds()
}
// 获得缓存数据的key列表
func GetKeys(pattern string) []string {
// 初始化变量
var keys []string
var cursor uint64 = 0
ctx := context.Background()
// 循环遍历获取匹配的键
for {
// 使用 SCAN 命令获取匹配的键
batchKeys, nextCursor, err := rdb.Scan(ctx, cursor, pattern, 100).Result()
if err != nil {
log.Errorf("Failed to scan keys: %v", err)
break
}
cursor = nextCursor
keys = append(keys, batchKeys...)
// 当 cursor 为 0表示遍历完成
if cursor == 0 {
break
}
}
return keys
}
// 批量获得缓存数据
func GetBatch(keys []string) []any {
if len(keys) == 0 {
return []any{}
}
// 获取缓存数据
result, err := rdb.MGet(context.Background(), keys...).Result()
if err != nil {
log.Errorf("Failed to get batch data: %v", err)
return []any{}
}
return result
}
// 获得缓存数据
func Get(key string) string {
ctx := context.Background()
value, err := rdb.Get(ctx, key).Result()
if err == redis.Nil || err != nil {
return ""
}
return value
}
// 获得缓存数据Hash
func GetHash(key string) map[string]string {
ctx := context.Background()
value, err := rdb.HGetAll(ctx, key).Result()
if err == redis.Nil || err != nil {
return map[string]string{}
}
return value
}
// 判断是否存在
func Has(keys ...string) bool {
ctx := context.Background()
exists, err := rdb.Exists(ctx, keys...).Result()
if err != nil {
return false
}
return exists >= 1
}
// 设置缓存数据
func Set(key string, value any) bool {
ctx := context.Background()
err := rdb.Set(ctx, key, value, 0).Err()
return err == nil
}
// 设置缓存数据与过期时间
func SetByExpire(key string, value any, expiration time.Duration) bool {
ctx := context.Background()
err := rdb.Set(ctx, key, value, expiration).Err()
return err == nil
}
// 删除单个
func Del(key string) bool {
ctx := context.Background()
err := rdb.Del(ctx, key).Err()
return err == nil
}
// 删除多个
func DelKeys(keys []string) bool {
if len(keys) == 0 {
return false
}
ctx := context.Background()
err := rdb.Del(ctx, keys...).Err()
return err == nil
}
// 限流查询并记录
func RateLimit(limitKey string, time, count int64) int64 {
ctx := context.Background()
result, err := rateLimitCommand.Run(ctx, rdb, []string{limitKey}, time, count).Result()
if err != nil {
log.Errorf("redis lua script err %v", err)
return 0
}
return result.(int64)
}

View File

@@ -43,6 +43,13 @@ database:
name: omc_db name: omc_db
backup: d:/local.git/ems.agt/restagent/database backup: d:/local.git/ems.agt/restagent/database
# Redis 缓存数据
redis:
port: 6379
host: "192.168.4.228"
password: ""
db: 0
mml: mml:
port: 4100 port: 4100
sleep: 200 sleep: 200

View File

@@ -10,6 +10,7 @@ import (
"strconv" "strconv"
"strings" "strings"
"ems.agt/lib/core/redis"
"ems.agt/lib/dborm" "ems.agt/lib/dborm"
"ems.agt/lib/global" "ems.agt/lib/global"
"ems.agt/lib/log" "ems.agt/lib/log"
@@ -133,6 +134,7 @@ func main() {
fmt.Printf("OMC restagent version: %s\n", global.Version) fmt.Printf("OMC restagent version: %s\n", global.Version)
log.Infof("========================= OMC restagent startup =========================") log.Infof("========================= OMC restagent startup =========================")
log.Infof("OMC restagent version: %s %s %s", global.Version, global.BuildTime, global.GoVer) log.Infof("OMC restagent version: %s %s %s", global.Version, global.BuildTime, global.GoVer)
err := dborm.InitDbClient(conf.Database.Type, conf.Database.User, conf.Database.Password, err := dborm.InitDbClient(conf.Database.Type, conf.Database.User, conf.Database.Password,
conf.Database.Host, conf.Database.Port, conf.Database.Name) conf.Database.Host, conf.Database.Port, conf.Database.Name)
if err != nil { if err != nil {
@@ -164,6 +166,9 @@ func main() {
os.Exit(4) os.Exit(4)
} }
// 连接redis
redis.Connect()
router := routes.NewRouter() router := routes.NewRouter()
// 开启监控采集 // 开启监控采集