redis/example/redis-bloom/main.go

156 lines
3.2 KiB
Go

package main
import (
"context"
"fmt"
"math/rand"
"github.com/redis/go-redis/v9"
)
func main() {
ctx := context.Background()
rdb := redis.NewClient(&redis.Options{
Addr: ":6379",
})
_ = rdb.FlushDB(ctx).Err()
fmt.Printf("# BLOOM\n")
bloomFilter(ctx, rdb)
fmt.Printf("\n# CUCKOO\n")
cuckooFilter(ctx, rdb)
fmt.Printf("\n# COUNT-MIN\n")
countMinSketch(ctx, rdb)
fmt.Printf("\n# TOP-K\n")
topK(ctx, rdb)
}
func bloomFilter(ctx context.Context, rdb *redis.Client) {
inserted, err := rdb.Do(ctx, "BF.ADD", "bf_key", "item0").Bool()
if err != nil {
panic(err)
}
if inserted {
fmt.Println("item0 was inserted")
} else {
fmt.Println("item0 already exists")
}
for _, item := range []string{"item0", "item1"} {
exists, err := rdb.Do(ctx, "BF.EXISTS", "bf_key", item).Bool()
if err != nil {
panic(err)
}
if exists {
fmt.Printf("%s does exist\n", item)
} else {
fmt.Printf("%s does not exist\n", item)
}
}
bools, err := rdb.Do(ctx, "BF.MADD", "bf_key", "item1", "item2", "item3").BoolSlice()
if err != nil {
panic(err)
}
fmt.Println("adding multiple items:", bools)
}
func cuckooFilter(ctx context.Context, rdb *redis.Client) {
inserted, err := rdb.Do(ctx, "CF.ADDNX", "cf_key", "item0").Bool()
if err != nil {
panic(err)
}
if inserted {
fmt.Println("item0 was inserted")
} else {
fmt.Println("item0 already exists")
}
for _, item := range []string{"item0", "item1"} {
exists, err := rdb.Do(ctx, "CF.EXISTS", "cf_key", item).Bool()
if err != nil {
panic(err)
}
if exists {
fmt.Printf("%s does exist\n", item)
} else {
fmt.Printf("%s does not exist\n", item)
}
}
deleted, err := rdb.Do(ctx, "CF.DEL", "cf_key", "item0").Bool()
if err != nil {
panic(err)
}
if deleted {
fmt.Println("item0 was deleted")
}
}
func countMinSketch(ctx context.Context, rdb *redis.Client) {
if err := rdb.Do(ctx, "CMS.INITBYPROB", "count_min", 0.001, 0.01).Err(); err != nil {
panic(err)
}
items := []string{"item1", "item2", "item3", "item4", "item5"}
counts := make(map[string]int, len(items))
for i := 0; i < 10000; i++ {
n := rand.Intn(len(items))
item := items[n]
if err := rdb.Do(ctx, "CMS.INCRBY", "count_min", item, 1).Err(); err != nil {
panic(err)
}
counts[item]++
}
for item, count := range counts {
ns, err := rdb.Do(ctx, "CMS.QUERY", "count_min", item).Int64Slice()
if err != nil {
panic(err)
}
fmt.Printf("%s: count-min=%d actual=%d\n", item, ns[0], count)
}
}
func topK(ctx context.Context, rdb *redis.Client) {
if err := rdb.Do(ctx, "TOPK.RESERVE", "top_items", 3).Err(); err != nil {
panic(err)
}
counts := map[string]int{
"item1": 1000,
"item2": 2000,
"item3": 3000,
"item4": 4000,
"item5": 5000,
"item6": 6000,
}
for item, count := range counts {
for i := 0; i < count; i++ {
if err := rdb.Do(ctx, "TOPK.INCRBY", "top_items", item, 1).Err(); err != nil {
panic(err)
}
}
}
items, err := rdb.Do(ctx, "TOPK.LIST", "top_items").StringSlice()
if err != nil {
panic(err)
}
for _, item := range items {
ns, err := rdb.Do(ctx, "TOPK.COUNT", "top_items", item).Int64Slice()
if err != nil {
panic(err)
}
fmt.Printf("%s: top-k=%d actual=%d\n", item, ns[0], counts[item])
}
}