场景需求
适用场景点赞,收藏等
设计思路
对于用户签到数据,如果每条数据都用K/V的方式存储,当用户量大的时候内存开销是非常大的。而位图(BitMap)是由一组bit位组成的,每个bit位对应0和1两个状态,虽然内部还是采用String类型存储,但Redis提供了一些指令用于直接操作位图,可以把它看作是一个bit数组,数组的下标就是偏移量。它的优点是内存开销小、效率高且操作简单,很适合用于签到这类场景。
Redis提供了以下几个指令用于操作位图:
SETBIT
GETBIT
BITCOUNT
实现方式(商品举例):
每一个商品会有一个ID,对应一个sitmap,商品ID为key,用户的ID为sitmap的位置,如果 此位置 为1 则已经点赞,如若没有则为0,取消点赞直接设置为0即可
golang语言事件:
package givelikes
import (
"context"
"fmt"
"github.com/go-redis/redis/v8"
)
//点赞功能开发
//gid 需要点赞的ID userid 用户ID
func GiveLike(gid int64,userid int64) (bool,error) {
var keys string = getKey(gid)
redis := GetRedis()
defer redis.Close()
res,err := redis.GetBit(context.Background(),keys,(userid-1)).Result()
if err != nil {
return false, err
}
if res == 1 {
return true,nil
}
res,err = redis.SetBit(context.Background(),keys,(userid-1),1).Result()
if err != nil {
return false, err
}
return true,nil
}
//查询是否已经点赞了
func GiveLikeSelect(gid int64,userid int64) (bool,error) {
var keys string = getKey(gid)
redis := GetRedis()
defer redis.Close()
res,err := redis.GetBit(context.Background(),keys,(userid-1)).Result()
if err != nil {
return false, err
}
if res == 1 {
return true,nil
}
return false,nil
}
//点赞数量
func GiveLikeCount(gid int64) (int64,error) {
var keys string = getKey(gid)
redisClient := GetRedis()
defer redisClient.Close()
count:= redis.BitCount{Start: 0,End: -1}
return redisClient.BitCount(context.Background(),keys,&count).Result()
}
func getKey (gid int64) string {
return fmt.Sprintf("give:%d",gid)
}