11:创建用户后默认进行link分组

7:创建用户后默认进行短链接分组

首先对短链接组进行分表,

用户已经进行分表了,一个用户可能默认有10条短链接,所以分组的表数量至少大于用户表数量。

短链接组 是为了方便用户与其创建的短链接进行对齐。

这里使用username作为分片元素,因为创建用户后,根据用户名来打到默认的分组表上。

dataSources:
  ds_0:
    dataSourceClassName: com.zaxxer.hikari.HikariDataSource #指定数据源  HikariCP连接池,这是一个高性能的 JDBC 连接池
    driverClassName: com.mysql.cj.jdbc.Driver # 指定jabc驱动
    jdbcUrl: jdbc:mysql://127.0.0.1:3306/link?useUnicode=true&characterEncoding=UTF-8&rewriteBatchedStatements=true&allowMultiQueries=true&serverTimezone=Asia/Shanghai #指定数据库位置以及一些参数
    username: root #数据库连接的用户名与密码
    password: 171612Cgj.

rules: # 这部分配置了两个主要的功能:数据分片和数据加密。
  - !SHARDING # 数据分片
    tables:
      t_user: # 对用户进行分表
        actualDataNodes: ds_0.t_user_${0..15} #数据实际存储节点: user_0 -> user_15 这16个表 存储在ds_0这个库下
        tableStrategy: #定义表的分片策略
          standard:
            shardingColumn: username #分片依据的字段
            shardingAlgorithmName: user_table_hash_mod #分片算法
      t_group: # 对短链接分组进行分表
        actualDataNodes: ds_0.t_group_${0..15}
        tableStrategy:
          standard:
            shardingColumn: username
            shardingAlgorithmName: group_table_hash_mod
    shardingAlgorithms: # 具体的分片算法
      user_table_hash_mod:
        type: HASH_MOD #具体的分片算法是:HASH_MOD
        props:
          sharding-count: 16 #分片数量 数据将根据分片算法被分散到 16 个不同的分表中
      group_table_hash_mod:
        type: HASH_MOD
        props:
          sharding-count: 16
  - !ENCRYPT #数据加密
    tables:
      t_user:
        columns: #需要加密的字段 t_user表中的phone字段和mail字段
          phone:
            cipherColumn: phone # 加密后存储的字段名这里直接用原列名表示加密覆盖原数据。
            encryptorName: common_encryptor # 使用的加密器名称。
          mail:
            cipherColumn: mail
            encryptorName: common_encryptor
        queryWithCipherColumn: true #是否在查询时使用加密列。
    encryptors:
      common_encryptor:
        type: AES # 使用的加密算法是AES加密算法  注意这个加密是可逆的,这是选它的一个原因
        props:
          aes-key-value: d6oadClrrb9A3GWo # 这是 AES 加密算法使用的密钥
props:
  sql-show: true #ShardingSphere 会在日志中显示实际执行的 SQL 语句以及逻辑sql
controller - 查询短链接分组集合 - listGroup
    /**
     * 查询短链接分组集合 / 当前用户有那些分组,每组里面有几个短链接
     */
    @GetMapping("/api/short-link/admin/v1/group")
    public Result<List<ShortLinkGroupRespDTO>> listGroup() { 
        return Results.success(groupService.listGroup());
    }
返回的响应 - ShortLinkGroupRespDTO
@Data
public class ShortLinkGroupRespDTO {

    /**
     * 分组标识
     */
    private String gid;

    /**
     * 分组名称
     */
    private String name;

    /**
     * 分组排序
     */
    private Integer sortOrder;

    /**
     * 分组下短链接数量
     */
    private Integer shortLinkCount;
}

当前用户下,所有分组:如下

在这里插入图片描述

service - 查询短链接分组集合 - listGroup

​ 根据登录的当前用户名 -> 查询当前用户的短链接分组集合

    @Override
    public List<ShortLinkGroupRespDTO> listGroup() {
        LambdaQueryWrapper<GroupDO> queryWrapper = Wrappers.lambdaQuery(GroupDO.class)
                .eq(GroupDO::getDelFlag, 0)
                .eq(GroupDO::getUsername, UserContext.getUsername())
                .orderByDesc(GroupDO::getSortOrder, GroupDO::getUpdateTime);
        List<GroupDO> groupDOList = baseMapper.selectList(queryWrapper);//拿到当前用户的所有短链接分组的gid信息
        
        Result<List<ShortLinkGroupCountQueryRespDTO>> listResult = shortLinkActualRemoteService
                .listGroupShortLinkCount(groupDOList.stream().map(GroupDO::getGid).toList());//通过微服务间的远程调用,将gid集合发送到project服务中。返回数据是一个list,里面的每个元素是gid和分组的数量
        
        List<ShortLinkGroupRespDTO> shortLinkGroupRespDTOList = BeanUtil.copyToList(groupDOList, ShortLinkGroupRespDTO.class);
        //ShortLinkGroupRespDTO内容是:分组标识gid,分组名称 name,分组排序sortOrder,分组下短链接数量:shortLinkCount
        
        shortLinkGroupRespDTOList.forEach(each -> {
            Optional<ShortLinkGroupCountQueryRespDTO> first = listResult.getData().stream()
                    .filter(item -> Objects.equals(item.getGid(), each.getGid()))
                    .findFirst();
            first.ifPresent(item -> each.setShortLinkCount(first.get().getShortLinkCount()));
        });
        //对于每一个 ShortLinkGroupRespDTO 对象,尝试从远程服务返回的 listResult 数据中找到匹配的 gid。如果找到匹配的 gid,则将对应的短链接数量 (shortLinkCount) 设置到当前的 ShortLinkGroupRespDTO 对象中。
        
        
        return shortLinkGroupRespDTOList;
    }

流程:

1:根据当前用户的username查询数据库,找到 List< GroupDO > 即一个用户短链接分组的集合,里面的主要内容是username下的gid

2:通过微服务的远程调用,获取到 List< ShortLinkGroupCountQueryRespDTO> 即一个集合,里面的每个元素是gid和分组的数量

3:对List< ShortLinkGroupCountQueryRespDTO> 这个集合中gid进行遍历找到匹配的gid,然后将短链接总数设置到 List< GroupDO > 中

短链接中台远程调用服务 - ShortLinkActualRemoteService
/**
 * 短链接中台远程调用服务
 */

@FeignClient(
        value = "short-link-project",
        url = "${aggregation.remote-url:}",
        configuration = OpenFeignConfiguration.class
)
public interface ShortLinkActualRemoteService {

    /**
     * 查询分组短链接总量
     *
     * @param requestParam 分组短链接总量请求参数
     * @return 查询分组短链接总量响应
     */
    @GetMapping("/api/short-link/v1/count")
    Result<List<ShortLinkGroupCountQueryRespDTO>> listGroupShortLinkCount(@RequestParam("requestParam") List<String> requestParam);

短链接分组查询返回参数 - ShortLinkGroupCountQueryRespDTO
/**
 * 短链接分组查询返回参数
 */
@Data
public class ShortLinkGroupCountQueryRespDTO {

    /**
     * 分组标识
     */
    private String gid;

    /**
     * 短链接数量
     */
    private Integer shortLinkCount;
}
注册用户以后 会对用户进行默认的分组
    @Transactional(rollbackFor = Exception.class) //数据库事务操作,只要出现异常就回滚
    @Override
    public void register(UserRegisterReqDTO requestParam) {
        //判断用户名是否存在
        if (!hasUsername(requestParam.getUsername())) {
            throw new ClientException(USER_NAME_EXIST); //如果用户名已存在,就抛出异常-用户名已存在
        }
        //调用redissonClient获取分布式锁RLock,锁的名字是LOCK_USER_REGISTER_KEY + 用户名 主要是为了防止大量请求注册同一个用户名
        RLock lock = redissonClient.getLock(LOCK_USER_REGISTER_KEY + requestParam.getUsername());
        if (!lock.tryLock()) { //尝试获取锁,如果获取锁失败,说明已经有人抢占这个用户名注册了
            throw new ClientException(USER_NAME_EXIST); //用户名已存在
        }
        try {
            int inserted = baseMapper.insert(BeanUtil.toBean(requestParam, UserDO.class));
            if (inserted < 1) { //插入操作成功会返回1
                throw new ClientException(USER_SAVE_ERROR);
            }
            groupService.saveGroup(requestParam.getUsername(), "默认分组"); //将当前的用户名保1却6存在一个分组中,便于管理
            userRegisterCachePenetrationBloomFilter.add(requestParam.getUsername()); //将当前的用户名放入布隆过滤器中,防止缓存穿透
        } catch (DuplicateKeyException ex) { //DuplicateKeyException -> 唯一键冲突 -> 用户名已存在 之所以还会出现这样的问题是因为:1:布隆过滤器有误判 2:高并发情况下那面会有极少数并发出现
            throw new ClientException(USER_EXIST);
        } finally {
            lock.unlock(); //最后不敢什么情况必须释放锁
        }
    }

用户注册以后会创建一个名为“默认分组”的分组,方便用户后续创建短链接的时候,放在默认分组中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HackerTerry

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值