2021-09-27 11:11:05 +03:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
"math/rand"
|
|
|
|
|
2023-01-23 09:48:54 +03:00
|
|
|
"github.com/redis/go-redis/v9"
|
2021-09-27 11:11:05 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
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])
|
|
|
|
}
|
|
|
|
}
|