代码拉取完成,页面将自动刷新
package tool
import (
"context"
"encoding/json"
"github.com/go-redis/redis/v8"
"github.com/pkg/errors"
"time"
)
// RedisZSetLRU 基于redis Zset实现 lru缓存
// RedisFreshDataCache 最新数据缓存,自动淘汰就数据
// 使用场景 如:缓存用户最后发送的5条消息,超过5条则自动删除,用户30分钟未发消息则会删除所有消息
type RedisZSetLRU struct {
rdb *redis.Client //
redisKey string //key
}
func NewRedisZSetLRU(rdb *redis.Client, RedisKey string) *RedisZSetLRU {
return &RedisZSetLRU{
rdb: rdb,
redisKey: RedisKey,
}
}
// Add 添加 //过期时间 //最大缓存个数
func (s *RedisZSetLRU) Add(Score float64, data interface{}, Expire time.Duration, MaxCacheNumber int64) error {
b, err := json.Marshal(data)
if err != nil {
return errors.Wrapf(err, "%+v %+v %+v %+v %+v", s.redisKey, Score, data, Expire, MaxCacheNumber)
}
if err := s.rdb.ZAdd(context.Background(), s.redisKey, &redis.Z{
Score: Score,
Member: b, //这里虽然是借口但是 只能存 string|[]byte|, 否则会报错 redis: can't marshal map[string]int (implement encoding.BinaryMarshaler)
}).Err(); err != nil {
return errors.Wrapf(err, "%+v %+v %+v %+v %+v", s.redisKey, Score, data, Expire, MaxCacheNumber)
}
//设置过期时间
if err := s.rdb.Expire(context.Background(), s.redisKey, Expire).Err(); err != nil {
return errors.Wrapf(err, "%+v %+v %+v %+v %+v", s.redisKey, Score, data, Expire, MaxCacheNumber)
}
//获取成员总个数
count := s.rdb.ZCard(context.Background(), s.redisKey).Val()
if count <= MaxCacheNumber {
return nil
}
//根据下标删除成员,前后都包含,分值越大,下标越大,这里删除小的
stop := count - MaxCacheNumber - 1
if stop < 0 {
return nil
}
if err := s.rdb.ZRemRangeByRank(context.Background(), s.redisKey, 0, stop).Err(); err != nil {
return errors.Wrapf(err, "%+v %+v %+v %+v %+v", s.redisKey, Score, data, Expire, MaxCacheNumber)
}
return nil
}
// GetScoreMax 获取分值最大的数据
func (s *RedisZSetLRU) GetScoreMax(out interface{}) (Score float64, err error) {
return s.GetOneByIndex(out, -1)
}
// GetScoreMin 获取分值最小的数据
func (s *RedisZSetLRU) GetScoreMin(out interface{}) (Score float64, err error) {
return s.GetOneByIndex(out, 0)
}
// GetOneByIndex 根据下标获取一条数据
func (s *RedisZSetLRU) GetOneByIndex(out interface{}, index int64) (Score float64, err error) {
//根据下标获取分值和成员,分值越大,下标越大
result, err := s.rdb.ZRangeWithScores(context.Background(), s.redisKey, index, index).Result()
if err != nil {
return 0, errors.Wrapf(err, "%+v", s.redisKey)
}
if len(result) <= 0 {
return 0, redis.Nil
}
//类型判断
var b []byte
if r, ok := result[0].Member.(string); ok == true {
b = []byte(r)
} else if r, ok := result[0].Member.([]byte); ok == true {
b = r
} else {
return 0, errors.New("unmarshal fail")
}
//解码数据
if err := json.Unmarshal(b, out); err != nil {
return 0, errors.Wrapf(err, "%+v", s.redisKey)
} else {
return result[0].Score, nil
}
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。