1
0
mirror of https://github.com/charlienet/go-mixed.git synced 2025-07-18 08:32:40 +08:00

use redis function(Version 7 and above is required

)
This commit is contained in:
2023-11-03 15:46:45 +08:00
parent 2f2af226ee
commit 01f426c5b2
6 changed files with 57 additions and 42 deletions

View File

@ -4,33 +4,18 @@ import (
"context"
"errors"
"strconv"
"sync"
"time"
_ "embed"
"github.com/charlienet/go-mixed/redis"
)
const (
// ARGV:偏移量offset数组
// KYES[1]: setbit操作的key
// 全部设置为1
setScript = `
for _, offset in ipairs(ARGV) do
redis.call("setbit", KEYS[1], offset, 1)
end
`
//go:embed bloom.lua
var redis_bloom_function string
//ARGV:偏移量offset数组
//KYES[1]: setbit操作的key
//检查是否全部为1
testScript = `
for _, offset in ipairs(ARGV) do
if tonumber(redis.call("getbit", KEYS[1], offset)) == 0 then
return false
end
end
return true
`
)
var once sync.Once
var ErrTooLargeOffset = errors.New("超出最大偏移量")
@ -44,6 +29,8 @@ type redisBitSet struct {
}
func newRedisStore(store redis.Client, key string, bits uint) *redisBitSet {
once.Do(func() { store.LoadFunction(redis_bloom_function) })
return &redisBitSet{
store: store,
key: key,
@ -51,16 +38,13 @@ func newRedisStore(store redis.Client, key string, bits uint) *redisBitSet {
}
}
func (s *redisBitSet) Set(offsets ...uint) error {
func (s *redisBitSet) Set(ctx context.Context, offsets ...uint) error {
args, err := s.buildOffsetArgs(offsets)
if err != nil {
return err
}
ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*500)
defer cancel()
_, err = s.store.Eval(ctx, setScript, []string{s.key}, args).Result()
_, err = s.store.FCall(ctx, "set_bit", []string{s.key}, args...).Result()
//底层使用的是go-redis,redis.Nil表示操作的key不存在
//需要针对key不存在的情况特殊判断
@ -82,7 +66,7 @@ func (s *redisBitSet) Test(offsets ...uint) (bool, error) {
ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*500)
defer cancel()
resp, err := s.store.Eval(ctx, testScript, []string{s.key}, args).Result()
resp, err := s.store.FCall(ctx, "test_bit", []string{s.key}, args...).Result()
// key 不存在,表示还未存放任何数据
if err == redis.Nil {
@ -103,8 +87,8 @@ func (s *redisBitSet) Clear() {
}
func (r *redisBitSet) buildOffsetArgs(offsets []uint) ([]string, error) {
args := make([]string, 0, len(offsets))
func (r *redisBitSet) buildOffsetArgs(offsets []uint) ([]any, error) {
args := make([]any, 0, len(offsets))
for _, offset := range offsets {
if offset >= r.bits {
return nil, ErrTooLargeOffset