在实际开发中,通过使用特征值来对数据进行去重复操作,而特征值首先需要具备过期时间和列表属性,但在redis中没有直接可用的数据结构,如果使用String则没有List特性,并且检索过程繁琐无法利用好redis,而List则无法使用过期时间。
查找资料后找到一种思路:使用有序集合进行排序,以时间作为值,定期执行清除过期数据任务
那么接下来开始实践
有序集合在Go中结构为redis.Z,包含Member 元素名与Score 分数
首先需要了需要用到的函数,用到的无非就是增,删,查三个函数(文章末尾有函数介绍):
ZAdd: 添加特征值元素,Member为特征值,Score为时间戳
ZRangeByScore: 通过分数范围取值,分数范围即为有效时间
ZRemRangeByScore: 通过时间范围删除特征值
除此之外,还需要一些时间函数,用于计算有效时间
获取分数(时间戳string)内的值
删除分数(时间戳float64)外的值
并且需要有两种返回形式,float64用于ZAdd的float型分数,而string用于检索时的分数
// TimeBfFloat 获取日期时间戳
func TimeBfFloat(beforeDay int) float64{
now := time.Now().Unix()
sub := 7 * 24 * time.Hour.Second()
return now - sub
}
// 获取string类型
func TimeBfString(beforeDay int) string{
beforeTime := TimeBfFloat(beforeDay)
return strconv.Itoa(int(beforeTime))
}
然后对Redis操作进行封装抽象
总的来说应该满足以下接口
type Eigenvalues interface{
// Set 设置特征值
// key 特征键
// eigenvalue 特征值
// timeout 超时时间(天数)
Set(key, eigenvalue string, timeout int) error
// Get 获取特征值
// key 特征键
// timeout 时间范围(天数)
Get(key string, timeout int) []string
// Del 删除特征值
// key 特征键
// timeout 超时时间(天数)
Del(key string, timeout int) error
}
添加一个或者多个元素到集合,如果元素已经存在则更新分数
client.ZAdd("key", redis.Z{20220524,"tizi"}).Err()
返回集合中索引范围内的元素,
ZRangeByScore根据分数从小到大排序,
ZRevRangeByScore根据分数从大到小排序
// 初始化查询条件, Offset和Count用于分页
op := redis.ZRangeBy{
Min:"2", // 最小分数
Max:"10", // 最大分数
Offset:0, // 起始位置
Count:5, // 数据条数
}
// return: []string
vals, err := client.ZRangeByScoreWithScores("key", op).Result()
根据分数范围删除元素
// 删除范围: 2<=分数<=5 的元素
client.ZRemRangeByScore("key", "2", "5")
// 删除范围: 2<=分数<5 的元素
client.ZRemRangeByScore("key", "2", "(5")
