tinyid源码解读 server部分

再来看服务端的

  • 我们通过查看client的源码,已经很清楚的发现, client获取号段的方式是 : 访问的url格式为"http://{0}/tinyid/id/nextSegmentIdSimple?token={1}&bizType=";

  • 那我们直接来server中Controller中的这个方法

  • 	@RequestMapping("nextSegmentIdSimple")
        public String nextSegmentIdSimple(String bizType, String token) {
            if (!tinyIdTokenService.canVisit(bizType, token)) {
                return "";
            }
            String response = "";
            try {
                SegmentId segmentId = segmentIdService.getNextSegmentId(bizType);
                response = segmentId.getCurrentId() + "," + segmentId.getLoadingId() + "," + segmentId.getMaxId()
                        + "," + segmentId.getDelta() + "," + segmentId.getRemainder();
            } catch (Exception e) {
                logger.error("nextSegmentIdSimple error", e);
            }
            return response;
        }
    
  • 首先判断当前bizType和token是否可以visit

  • 这是用token判断client是否合法

  • 然后就是segmentIdService.getNextSegmentId(bizType);方法了 这个方法就是server的核心了

  • 	@Override
        @Transactional(isolation = Isolation.READ_COMMITTED)
        public SegmentId getNextSegmentId(String bizType) {
            // 获取nextTinyId的时候,有可能存在version冲突,需要重试
            for (int i = 0; i < Constants.RETRY; i++) {
                TinyIdInfo tinyIdInfo = tinyIdInfoDAO.queryByBizType(bizType);//1
                if (tinyIdInfo == null) {
                    throw new TinyIdSysException("can not find biztype:" + bizType);
                }
                Long newMaxId = tinyIdInfo.getMaxId() + tinyIdInfo.getStep();
                Long oldMaxId = tinyIdInfo.getMaxId();
                int row = tinyIdInfoDAO.updateMaxId(tinyIdInfo.getId(), newMaxId, oldMaxId, tinyIdInfo.getVersion(),
                        tinyIdInfo.getBizType());
                if (row == 1) {
                    tinyIdInfo.setMaxId(newMaxId);
                    SegmentId segmentId = convert(tinyIdInfo);
                    logger.info("getNextSegmentId success tinyIdInfo:{} current:{}", tinyIdInfo, segmentId);
                    return segmentId;
                } else {
                    logger.info("getNextSegmentId conflict tinyIdInfo:{}", tinyIdInfo);
                }
            }
            throw new TinyIdSysException("get next segmentId conflict");
        }
    
  • 1处根据bizType直接查询数据库,获取当前短号信息

  • String sql = "select id, biz_type, begin_id, max_id," +
            " step, delta, remainder, create_time, update_time, version" +
            " from tiny_id_info where biz_type = ?";
    
  • 将查询结果封装到TinyIdInfo这个pojo中,然后返回

  • 如果没有查询到,说明没有这个业务类型,则直接抛出异常

  • 然后就是获取段号的逻辑了

  • 新的maxId是旧的maxId+step

  • 然后这里用的version参数来控制的乐观锁

  • String sql = "update tiny_id_info set max_id= ?," +
                    " update_time=now(), version=version+1" +
                    " where id=? and max_id=? and version=? and biz_type=?";
    
  • sql语句如上

  • 注意到这里会一直尝试Constant.RETRY次,来进行’CAS’

  • 在Constant这个类中定义了如下参数

  • public class Constants {
        /**
         * 预加载下个号段的百分比
         */
        public static final int LOADING_PERCENT = 20;
        /**
         * 重试次数
         */
        public static final int RETRY = 3;
    
        private Constants() {
    
        }
    }
    
  • 重试的参数是3次

  • 以此来解决并发的问题

  • 同时这里有事务,保证读和写是同一个事务

  • 大体的获取的逻辑是这样

  • 其他的方法也大致是这个逻辑,没有什么不同

  • 其他的也就一个nextId方法

  • 逻辑和客户端的其实一样,都是有一个current,一个next号段

  • 然后来获取id,如果current为空,或者怎样,去查询

  • 区别在于这里的获取,不是http去向服务端请求,因为自己就是服务端

  • 而是直接通过数据库查询

  • 而我也发现了一个问题,如果通过nextId方法,server端,是将号段放在自己的内存中,这个可以直接client以nextId方法请求

  • 而如果nextSegmentId的话,是不涉及自己的内存中的号段的,而是直接去数据库中查询,
    在这里插入图片描述

  • 这个图很清晰

  • nextSegment方法会绕过server的内存

  • 然后这里是有一个filter

  • @WebFilter(urlPatterns = "/*", filterName = "requestFilter")
    
  • 进行了个处理

  • 哦哦,就是打印了日志,也没干什么

  • 这里有动态的数据源的机制

  • 之后我会去了解一下,这里先mark一下

  • https://blog.csdn.net/jiachunchun/article/details/94569124

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值