一、特性说明
- set集合内部元素无序且不重复
- set集合底层是由值为null的hash表实现
二、常用命令
(一)SADD
命令格式: sadd key member [member]
功能:往集合中存入元素,元素存在则忽略
demo说明:
(二)SMEMBERS
命令格式: smembers key
功能:获取集合key中所有元素
demo说明:
(三)SREM
命令格式: srem key member [member]
功能:从集合中删除元素
demo说明:
(四)SCARD
命令格式: scard key
功能:获取集合key中的元素个数
demo说明:
(五)SISMEMBER
命令格式: sismember key member
功能:判断member元素否存在集合key中
demo说明:
(六)SRANDMEMBER
命令格式: srandmember key [count]
功能:从集合key中选出count个元素,元素不从集合中删除
demo说明:
(七)SPOP
命令格式: spop key [count]
功能:从集合key中选出count个元素,元素从集合中删除
demo说明:
(八)SINTER
命令格式: sinter key [key]
功能:交集运算
demo说明:
(九)SINTERSTORE
命令格式: sinterstore destination key [key]
功能:交集运算,并把结果存入新集合destination
demo说明:
(十)SUNION
命令格式: sunion key [key]
功能:并集运算
demo说明:
(十一)SUNIONSTORE
命令格式: sunionstore destination key [key]
功能:并集运算,并把结果存入新集合destination
(十二)SDIFF
命令格式: sdiff key [key]
功能:差集运算
demo说明:
(十三)SDIFFSTORE
命令格式: sdiffstore destination key [key]
功能:差集运算,并把结果存入新集合destination
demo说明:
三、应用场景
(一)抽奖小程序
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());
}