微关系计算解决方案
1. 业务分析
微博微关系:
共同关注:计算出A和B共同关注的人有哪些?
我关注的人也关注他:是计算出A关注的人群中,有哪些人同时和A一样关注了B
2. 技术方案
传统开发,采用数据库持久化关系数据,如下
关注表:
| id | user_name | fans |
|---|---|---|
| 1 | A | C |
| 2 | A | B |
| 3 | B | A |
| 4 | C | A |
| ... | ... | ... |
如果是采用数据库来实现用户的关系,一般SQL怎么写?
- 例如:A关注2个人,B关注100个人,计算2人的共同关注那些人?
- SQL的写法,一般是采用in 或 not in 来实现。但是对于互联网高并发的系统来说,in 或not in 明显不适合。
select fans from table_name where user_name='A' and fans in (select fans from table_name where user_name='B')
复制代码
- 一般的做法是采用redis的set集合来实现。
Redis Set数据结构,非常适合存储好友、关注、粉丝、感兴趣的人的集合。然后采用set的命令就能得出我们想要的数据。
sinter:获得A和B两个用户的共同好友sismember:判断C是否为B的好友scard:获取好友数量
3. 实战:共同关注
- 关注顺序
- A关注:B C D
- B关注:A C D
- C关注: A
- D关注:A B
- 微关系:
- A和B的共同关注={C,D}
共同关注:redis计算出A和B共同关注的人有哪些?
@ApiOperation(value="求2个用户的关注交集")
@GetMapping(value = "/intersect")
public List<UserVO> intersect(Integer userId1, Integer userId2){
return this.relationService.intersect(userId1,userId2);
}
复制代码
/**
* 求2个用户的关注交集
*/
public List<UserVO> intersect(Integer userId1,Integer userId2){
SetOperations<String, Integer> opsForSet = redisTemplate.opsForSet();
String fans1 = Constants.KEY_FANS + userId1;
String fans2 = Constants.KEY_FANS + userId2;
//求2个集合的交集
Set<Integer> sets= opsForSet.intersect(fans1,fans2);
//返回交集的用户信息
return this.getUserInfo(sets);
}
复制代码
4. 实战:我关注的人也关注他
- 关注顺序
- A关注:B C D
- B关注:A C D
- C关注: A
- D关注:A B C
- 微关系:
A关注的人XXX也关注C- 求出XXX有哪些人?
-
- A关注的人有哪些{B,C,D}
-
- B关注的人是否关注C-true
-
- C关注的人是否关注C-false
-
- D关注的人是否关注C-true
XXX={B,D}
-
案例1:A关注的人XXX也关注C
查询出XXX有哪些人
/**
*- 关注顺序
* - A关注:B C D
* - B关注:A C D
* - C关注: A
* - D关注:A B C
* - 微关系:
* - A关注的人XXX也关注C:`XXX={B,D} `
* - 1. A关注的人有哪些{B,C,D}
* - 2. B关注的人是否关注C-true
* - 3. C关注的人是否关注C-false
* - 4. D关注的人是否关注C-true
* @param userId1 A
* @param userId2 C
* @return XXX: A关注的人XXX也关注C
*/
public List<UserVO> getUser1(String userId1, String userId2) {
SetOperations<String, Integer> opsForSet = redisTemplate.opsForSet();
Set<Integer> users = new HashSet<>();
String followeekey1 = Constants.KEY_FANS + userId1;
//a关注的人是否有c
Boolean c = opsForSet.isMember(followeekey1, userId2);
if (c) {
//a关注人有哪些
Set<Integer> aMembers = opsForSet.members(followeekey1);
if (aMembers != null) {
aMembers.forEach(m -> {
String memberKsy = Constants.KEY_FANS + m;
//a关注的人是否有关注c
Boolean isMember = opsForSet.isMember(memberKsy, userId2);
if (isMember) {
users.add(m);
}
});
//根据用户id查询用户信息
return this.getUserInfo(users);
}
}
return null;
}
复制代码




近期评论