咱们有一个业务场景是须要将用户邀请的下级用户根据其用户等级给统计出来(不止统计一级).
现有的解决方案:
mysql中一张用户表
主要的3个字段:user_id, parent _id,level,
典型的一个树形结构.
由于数据量很大,查询次数不少,因此重算这数据基本上重算一次要花个几分钟.mysql
优化版本1:
假如我将没全部用户对应的全部直接下级用户的id取出,存放到redis中的数组,像这样redis
U:110->[111,112,113,...]
sql
将用户等级也放到redis中,像这样 数组
L:110->0
优化
而后经过map的方式取到下级的下级用户并合并起来,再经过用户等级进行分组。code
users.stream.map(u-> jedis.lrange(0,-1)).flatMap(u-> u).collect(grouppingBy(u-> jedis.get("L:" + u)))...
内存
LRANGE
时间复杂度:O(S+N), S 为偏移量 start , N 为指定区间内元素的数量。`
优化结果:
计算机器:I5 六代 8G内存
时间:25秒get
优化版本2:
使用Set存放用户,经过SUNION命令获取下级IDio
时间复杂度:O(N), N 是全部给定集合的成员数量之和。
stream
获取当前下级的用户代码则更简单了,首先将当前用户经过CPU并行的方式把SET的key计算出来,而后经过SUNION将全部的用户取出来:
private Set<String> downLevelAllUser(Set<String> users) { return jedis.sunion(users.parallelStream().map(s -> "U:" + s ).collect(Collectors.toList()).toArray(new String[0])); }
这些用户的等级都查出来,那就获取他们的用户等级并进行分组.
private Map<String, List<String>> groupUser(Set<String> users) { return jedis.mget(users.parallelStream().map(u -> "L:" + u) .collect(Collectors.toList()).toArray(new String[0])) .parallelStream().collect(Collectors.groupingBy(r -> r)); }
主要功能都实现了,那么试试计算8级所花时间
public List<Map<String, Integer>> downLevel8UserRole(int start_user) { Set<String> u1 = downLevel1Users(start_user); Map<String, List<String>> m1 = groupUser(u1); Set<String> u2 = downLevelAllUser(u1); Map<String, List<String>> m2 = groupUser(u2); Set<String> u3 = downLevelAllUser(u2); Map<String, List<String>> m3 = groupUser(u3); Set<String> u4 = downLevelAllUser(u3); Map<String, List<String>> m4 = groupUser(u4); Set<String> u5 = downLevelAllUser(u4); Map<String, List<String>> m5 = groupUser(u5); Set<String> u6 = downLevelAllUser(u5); Map<String, List<String>> m6 = groupUser(u6); Set<String> u7 = downLevelAllUser(u6); Map<String, List<String>> m7 = groupUser(u7); Set<String> u8 = downLevelAllUser(u7); Map<String, List<String>> m8 = groupUser(u8); return Arrays.asList(m1, m2, m3, m4, m5, m6, m7, m8).parallelStream().map(m -> { Map<String, Integer> newMap = new HashMap<>(); m.forEach((k, v) -> newMap.put(k, v.size())); return newMap; }).collect(Collectors.toList()); }
优化结果:
总用户数为:120W
计算机器:I5 六代 8G内存
时间:4秒
好了,优化完毕了,大神们还有什么高招,欢迎来指导!!!!!!