Redis核心数据结构之Set(四)

266 阅读5分钟

一、特性说明

  • set集合内部元素无序且不重复
  • set集合底层是由值为null的hash表实现

二、常用命令

(一)SADD

命令格式: sadd key member [member]

功能:往集合中存入元素,元素存在则忽略

demo说明:

image.png

(二)SMEMBERS

命令格式: smembers key

功能:获取集合key中所有元素

demo说明:

image.png

(三)SREM

命令格式: srem key member [member]

功能:从集合中删除元素

demo说明:

image.png

(四)SCARD

命令格式: scard key

功能:获取集合key中的元素个数

demo说明:

image.png

(五)SISMEMBER

命令格式: sismember key member

功能:判断member元素否存在集合key中

demo说明:

image.png

(六)SRANDMEMBER

命令格式: srandmember key [count]

功能:从集合key中选出count个元素,元素不从集合中删除

demo说明:

image.png

(七)SPOP

命令格式: spop key [count]

功能:从集合key中选出count个元素,元素从集合中删除

demo说明:

image.png

(八)SINTER

命令格式: sinter key [key]

功能:交集运算

demo说明:

image.png

(九)SINTERSTORE

命令格式: sinterstore destination key [key]

功能:交集运算,并把结果存入新集合destination

demo说明: image.png

(十)SUNION

命令格式: sunion key [key]

功能:并集运算

demo说明:

image.png

(十一)SUNIONSTORE

命令格式: sunionstore destination key [key]

功能:并集运算,并把结果存入新集合destination

image.png

(十二)SDIFF

命令格式: sdiff key [key]

功能:差集运算

demo说明:

image.png

(十三)SDIFFSTORE

命令格式: sdiffstore destination key [key]

功能:差集运算,并把结果存入新集合destination

demo说明:

image.png

三、应用场景

(一)抽奖小程序

1、需求

用户可以选择某个产品参与抽奖,并且可以看到已参与的用户。后台开奖可以抽取一位或多位中奖者

2、设计

  • 用户参与抽奖时将用户id放入集合中
  • 返回集合所有用户id,再根据用户id去查询用户信息,则得到所有参与者
  • 系统开奖时从集合取出一个用户但是不删除
  • 缓存键设计为 luck:product:{产品id}

3、开发

用户参与抽奖接口

@ApiOperation("用户参与抽奖")
@PostMapping(value = "/luckDraw")
public RestResponse luckDraw(Integer year, Integer month,Integer day) throws Exception{

    Long userId = 2000L;

    //设计的键  业务:表名:{id}
    String key = "luck:product:1000";

    //判断是否已参与过
    Boolean check = redisTemplate.opsForSet().isMember(key,userId);
    if(check){
        return new RestResponse(0,"你已参与");
    }

    redisTemplate.opsForSet().add(key,userId);

    return new RestResponse(0,"参与成功");

}

获取所有已参与的用户接口

@ApiOperation("获取所有已参与的用户")
@PostMapping(value = "/getLuckDrawAllUser")
public void getLuckDrawAllUser(Long productId) throws Exception{

    //设计的键  业务:表名:{id}
    String key = "luck:product:"+String.valueOf(productId);

    //判断是否已参与过
    Set members = redisTemplate.opsForSet().members(key);

    System.out.println(members);


}

后台开奖

public void drawResult() throws Exception{

    String key = "luck:product:1000";

    Object o = redisTemplate.opsForSet().randomMember(key);
    System.out.println(o);

}

(二)微博社交关系

1、需求

实现如下社交关系列表
(1)粉丝列表
(2)我关注的人
(3)共同关注
(4)我关注的人也关注他
(5)我可能认识的人

2、设计

  • 将每个人的粉丝放入一个集合set,key设计为{userId}:fans
  • 将每个人的关注的人放入一个集合set,key设计为{userId}:follow
  • 粉丝列表的实现则直接获取粉丝集合
  • 我关注的人列表的实现则直接获取我关注的人的集合
  • A和B共同关注的的集合则 A关注的人的集合和 B关注的人的集合取交集
  • A关注的人也关注C,则取A关注的人的集合和 C粉丝集合取交集
  • A可能认识的人,则先从A的关注的人取出一个D,然后取D和A的差集

3、开发

关注用户接口

@ApiOperation("关注用户")
@PostMapping(value = "/followUser")
public RestResponse followUser(Long followUserId) throws Exception{
    //从session或者token中获取用户id
    Long userId = 1000L;

    //我关注的人的集合键
    String followKey = "follow:"+String.valueOf(userId);

    //我关注的人的粉丝集合键
    String fansKey = "fans:"+String.valueOf(followUserId);


    Boolean member = redisTemplate.opsForSet().isMember(followKey, followUserId);
    if(member){
        return new RestResponse(600020,"你已关注了他");
    }

    redisTemplate.opsForSet().add(followKey,followUserId);

    redisTemplate.opsForSet().add(fansKey,userId);

    return new RestResponse(0,"关注成功");

}

获取粉丝列表接口

@ApiOperation("获取粉丝列表")
@PostMapping(value = "/getFansList")
public RestResponse getFansList() throws Exception{

    //从session或者token中获取用户id
    Long userId = 2000L;

    //我的粉丝集合键
    String fansKey = "fans:"+String.valueOf(userId);

    Set members = redisTemplate.opsForSet().members(fansKey);

    //根据id查询头像等信息(粉丝太多,需要自行考虑分页,这里暂时省略)

    return new RestResponse(0,"获取成功",members);
}

获取我关注的人列表接口

@ApiOperation("获取我关注的人列表")
@PostMapping(value = "/getMyFollowList")
public RestResponse getMyFollowList() throws Exception{

    //从session或者token中获取用户id
    Long userId = 1000L;

    //我的关注的集合键
    String followKey = "follow:"+String.valueOf(userId);

    Set members = redisTemplate.opsForSet().members(followKey);

    //根据id查询头像等信息(粉丝太多,需要自行考虑分页,这里暂时省略)

    return new RestResponse(0,"获取成功",members);
}

获取共同关注的人的列表接口

@ApiOperation("获取共同关注的人的列表")
@PostMapping(value = "/getCommonFollowList")
public RestResponse getCommonFollowList(Long otherUserId) throws Exception{

    //从session或者token中获取用户id
    Long userId = 1000L;

    //我的关注的集合键
    String followKey = "follow:"+String.valueOf(userId);
    //他的关注的集合键
    String otherFollowKey = "follow:"+String.valueOf(otherUserId);

    Set intersect = redisTemplate.opsForSet().intersect(followKey, otherFollowKey);

    //根据id查询头像等信息(粉丝太多,需要自行考虑分页,这里暂时省略)

    return new RestResponse(0,"获取成功",intersect);
}

获取我关注的人也关注他的列表接口

@ApiOperation("获取我关注的人也关注他的列表")
@PostMapping(value = "/getMyFollowFollowHeList")
public RestResponse getMyFollowFollowHeList(Long heUserId) throws Exception{

    //从session或者token中获取用户id
    Long userId = 1000L;

    //我的关注的集合键
    String followKey = "follow:"+String.valueOf(userId);
    //他粉丝的集合键
    String heFollowKey = "fans:"+String.valueOf(heUserId);
    //取交集
    Set intersect = redisTemplate.opsForSet().intersect(followKey, heFollowKey);

    //根据id查询头像等信息(粉丝太多,需要自行考虑分页,这里暂时省略)

    return new RestResponse(0,"获取成功",intersect);
}

获取我可能认识的人的列表接口

@ApiOperation("获取我可能认识的人的列表")
@PostMapping(value = "/getMyMayKnowList")
public RestResponse getMyMayKnowList() throws Exception{

    //从session或者token中获取用户id
    Long userId = 1000L;

    //我的关注的集合键
    String followKey = "follow:"+String.valueOf(userId);

    //取出一个粉丝  这里暂时用一个粉丝来举例
    Object result = redisTemplate.opsForSet().randomMember(followKey);
    Long id = Long.valueOf(result.toString());
    if(!ObjectUtils.isEmpty(id)){
        //他关注的的集合键
        String heFollowKey = "follow:"+String.valueOf(id);
        //取差集
        Set intersect = redisTemplate.opsForSet().difference(heFollowKey,followKey);

        //根据id查询头像等信息(粉丝太多,需要自行考虑分页,这里暂时省略)

        return new RestResponse(0,"获取成功",intersect);
    }

    return new RestResponse(0,"获取成功",Collections.emptyList());

}