海量数据处理商用短链接生成器平台 - 10

news2024/9/29 18:02:12

第二十一章 短链服务冗余双写-链路测试和异常消息处理实战

第1集 冗余双写MQ架构-消费者配置自动创建队列和集群测试

简介: 冗余双写MQ架构-MQ消费者配置自动创建队列

  • controller-service层开发
  • 配置文件配置MQ
##----------rabbit配置--------------
spring.rabbitmq.host=120.79.150.146
spring.rabbitmq.port=5672
#需要手工创建虚拟主机
spring.rabbitmq.virtual-host=dev
spring.rabbitmq.username=admin
spring.rabbitmq.password=password
#消息确认方式,manual(手动ack) 和auto(自动ack)
spring.rabbitmq.listener.simple.acknowledge-mode=auto
  • 大家遇到的问题 (不会自动创建队列)

    • 加了@bean配置交换机和queue,启动项目却没自动化创建队列
    • RabbitMQ懒加载模式, 需要配置消费者监听才会创建,
    @RabbitListener(queues = "short_link.add.link.queue")
    
  • 另外种方式(若Mq中无相应名称的队列,会自动创建Queue)

    @RabbitListener(queuesToDeclare = { @Queue("short_link.add.link.queue") })
    
  • 链路测试-多节点启动

第2集 冗余双写架构-MQ消费者异常重试处理方案链路

简介: 冗余双写架构-MQ消费者异常处理方案讲解

  • 消费者异常情况处理
    • 业务代码自己重试
    • 组件重试
  • RabbitMQ配置重试
#开启重试,消费者代码不能添加try catch捕获不往外抛异常
spring.rabbitmq.listener.simple.retry.enabled=true
#最大重试次数
spring.rabbitmq.listener.simple.retry.max-attempts=4
# 重试消息的时间间隔,5秒
spring.rabbitmq.listener.simple.retry.initial-interval=5000
  • 问题:多次重试失败怎么处理?

在这里插入图片描述

  • 解决方式:RepublishMessageRecoverer
    • 消息重试一定次数后,用特定的routingKey转发到指定的交换机中,方便后续排查和告警
第3集 冗余双写架构-MQ消费者异常重试处理方案编码实战

简介: 冗余双写架构-MQ消费者异常重试处理方案编码实战

  • 解决方式:RepublishMessageRecoverer
    • 消费消息重试一定次数后,用特定的routingKey转发到指定的交换机中,方便后续排查和告警
    • 注意
      • 消息消费确认使用自动确认方式
@Configuration
@Data
public class RabbitMQErrorConfig {


    private String shortLinkErrorExchange = "short_link.error.exchange";

    private String shortLinkErrorQueue = "short_link.error.queue";

    private String shortLinkErrorRoutingKey = "short_link.error.routing.key";

    @Autowired
    private RabbitTemplate rabbitTemplate;


    /**
     * 异常交换机
     * @return
     */
    @Bean
    public TopicExchange errorTopicExchange(){
        return new TopicExchange(shortLinkErrorExchange,true,false);
    }

    /**
     * 异常队列
     * @return
     */
    @Bean
    public Queue errorQueue(){
        return new Queue(shortLinkErrorQueue,true);
    }

    /**
     * 队列与交换机进行绑定
     * @return
     */
    @Bean
    public Binding BindingErrorQueueAndExchange(Queue errorQueue,TopicExchange errorTopicExchange){
        return BindingBuilder.bind(errorQueue).to(errorTopicExchange).with(shortLinkErrorRoutingKey);
    }


    /**
     * 配置 RepublishMessageRecoverer
     * 用途:消息重试一定次数后,用特定的routingKey转发到指定的交换机中,方便后续排查和告警
     *
     * 顶层是 MessageRecoverer接口,多个实现类
     *
     * @return
     */
    @Bean
    public MessageRecoverer messageRecoverer(){
        return new RepublishMessageRecoverer(rabbitTemplate,shortLinkErrorExchange,shortLinkErrorRoutingKey);
    }


}

第二十二章 短链服务冗余双写问题抛出-MQ消费者链路开发

第1集 冗余双写架构-高并发下短链码生成端问题抛出

简介: 冗余双写架构-短链码生成端问题抛出

  • 短链码是哪里生成?生产者端 还是消费者端
    • 生产者生成短链码,下面的情况
      • 用户A生成短链码AABBCC,查询数据库不存在,发送MQ,插入数据库成功
      • 用户B生成短链码AABBCC,查询数据库不存在,发送MQ,插入数据库失败
    • 消费者生成短链码,下面的情况
      • 用户A生成短链码AABBCC ,C端先插入,B端还没插入
      • 用户B也生成短链码AABBCC ,B端先插入,C端还没插入
      • 用户A生成短链码AABBCC ,B端插入
      • 用户B生成短链码AABBCC ,C端插入

在这里插入图片描述

第2集 冗余双写架构-商家创建短链-C端消费者开发实战

简介: 冗余双写架构-商家创建短链-C端消费者开发实战

  • C端消费者开发实战
//判断短链域名是否合法
//判断组名是否合法
//生成长链摘要
//生成短链码
//加锁
//查询短链码是否存在
//构建短链对象
//保存数据库
第3集 冗余双写架构-商家创建短链-B端消费者开发实战

简介: 冗余双写架构-商家创建短链-B端消费者开发实战

  • B端消费者开发实战
//生成长链摘要
//判断短链域名是否合法
//判断组名是否合法
//生成短链码
//加锁(加锁再查,不然查询后,加锁前有线程刚好新增)
//查询短链码是否存在
//构建短链mapping对象
//保存数据库
 public boolean handlerAddShortLink(EventMessage eventMessage) {


        Long accountNo = eventMessage.getAccountNo();
        String messageType = eventMessage.getEventMessageType();


        ShortLinkAddRequest addRequest = JsonUtil.json2Obj(eventMessage.getContent(), ShortLinkAddRequest.class);
        //短链域名校验
        DomainDO domainDO = checkDomain(addRequest.getDomainType(), addRequest.getDomainId(), accountNo);
        //校验组是否合法
        LinkGroupDO linkGroupDO = checkLinkGroup(addRequest.getGroupId(), accountNo);
        //长链摘要
        String originalUrlDigest = CommonUtil.MD5(addRequest.getOriginalUrl());


        //生成短链码
        String shortLinkCode = shortLinkComponent.createShortLinkCode(addRequest.getOriginalUrl());


        //TODO 加锁




        //先判断是否短链码被占用
        ShortLinkDO ShortLinCodeDOInDB = shortLinkManager.findByShortLinCode(shortLinkCode);




        if(ShortLinCodeDOInDB == null){


            //C端处理
            if (EventMessageType.SHORT_LINK_ADD_LINK.name().equalsIgnoreCase(messageType)) {
                ShortLinkDO shortLinkDO = ShortLinkDO.builder()
                        .accountNo(accountNo)
                        .code(shortLinkCode)
                        .title(addRequest.getTitle())
                        .originalUrl(addRequest.getOriginalUrl())
                        .domain(domainDO.getValue())
                        .groupId(linkGroupDO.getId())
                        .expired(addRequest.getExpired())
                        .sign(originalUrlDigest)
                        .state(ShortLinkStateEnum.ACTIVE.name())
                        .del(0)
                        .build();
                shortLinkManager.addShortLink(shortLinkDO);
                return true;


            } else if (EventMessageType.SHORT_LINK_ADD_MAPPING.name().equalsIgnoreCase(messageType)) {


                //B端处理
                GroupCodeMappingDO groupCodeMappingDO = GroupCodeMappingDO.builder()
                        .accountNo(accountNo)
                        .code(shortLinkCode)
                        .title(addRequest.getTitle())
                        .originalUrl(addRequest.getOriginalUrl())
                        .domain(domainDO.getValue())
                        .groupId(linkGroupDO.getId())
                        .expired(addRequest.getExpired())
                        .sign(originalUrlDigest)
                        .state(ShortLinkStateEnum.ACTIVE.name())
                        .del(0)
                        .build();


                groupCodeMappingManager.add(groupCodeMappingDO);
                return true;


            }
        }




        return false;


    }
第4集 同个URL生成短链码随机库表位问题和解决方案讲解

简介: 同个URL生成短链码随机库表位问题和解决方案讲解

  • 需求

    • App的下载链接,需要进行投放广告,并验证不同渠道的效果质量
    • 渠道:抖音、百度、新浪微博、知乎、B站、头条等
    • 最终下载地址一样,但是需要区分不通渠道效果质量
  • 问题抛出

    • MurmurHash对同个url产生后的值是一样的,但是随机拼接了库表位,最终生成的短链码就导致可能不一致的情况,怎么解决?

    • 问题重现

    • 答案

      • MurmurHash后的短链码,拼接随机库表位需要固定
      • 采用hashCode取模生成对应的库表位
第5集 MurmurHash短链码改进之生成固定库表位编码实战

简介: MurmurHash短链码改进之生成固定库表位编码实战

  • 编码实战
    /**
     * 获取随机的后缀
     * @return
     */
    public static String getRandomTableSuffix(String code){
        int hashCode = code.hashCode();
        int num = Math.abs(hashCode) % tableSuffixList.size();
        return tableSuffixList.get(num);
    }




   /**
     * 获取随机的前缀
     * @return
     */
    public static String getRandomDBPrefix(String code){


        int hashCode = code.hashCode();
        int num = Math.abs(hashCode) % dbPrefixList.size();
        return dbPrefixList.get(num);
    }
第6集 同个URL生成不唯一短链码问题和解决方案讲解

简介: 同个URL生产唯一短链码问题和解决方案讲解

  • 需求

    • App的下载链接,需要进行投放广告,并验证不同渠道的效果质量
    • 渠道:抖音、百度、新浪微博、知乎、B站、头条等
    • 最终下载地址一样,但是需要区分不通渠道效果质量
  • 问题抛出:

    • 解决了随机库表问题后,一个URL怎么生成多个不一样的短链码

    • URL重复生成短链问题

      • 如果原始URL不做处理,则重复概率很高
      • 方案:原始url 拼接随机串,访问前去除
    • 问题重现

    • 答案

      • 生产者发送消息携带一个时间戳 或 随机id
      • 原始URL开头拼接特殊字段
        • 原生 https://baidu.com
        • 拼接后 1469558440337604610||https://baidu.com
        • 如果冲突,则编号递增1
      • 访问前截取去除
第7集 同个URL生成不唯一短链码问题和解决方案编码实战

简介: 同个URL生成不唯一短链码问题和解决方案编码实战

  • 工具类编写
    /**
     * URL增加前缀
     * @param url
     * @return
     */
    public static String addUrlPrefix(String url){
        return IDUtil.geneSnowFlakeID()+"&"+url;
    }


    /**
     * URL移除前缀
     * @param url
     * @return
     */
    public static String removeUrlPrefix(String url){
        String originalUrl = url.substring(url.indexOf("&")+1);
        return originalUrl;
    }


    /**
     * 如果短链码重复,则调用这个方法
     * url前缀编号递增1,如果还是用雪花算法,则容易C和B端不一致,所以采用原先的id递增1
     * @param url
     * @return
     */
    public static String addUrlPrefixVersion(String url){
        String result = url.substring(0,url.indexOf("&"));
        //原始地址
        String originalUrl = url.substring(url.indexOf("&")+1);
        //新id编号
        Long newIdValue = Long.parseLong(result)+1;
        return newIdValue+"&"+originalUrl;
    }


  • 编码实战
//发送MQ消息
 @Override
    public JsonData createShortLink(ShortLinkAddRequest request) {


        Long accountNo = LoginInterceptor.threadLocal.get().getAccountNo();


        String originalUrl = CommonUtil.addUrlPrefix(request.getOriginalUrl());
        request.setOriginalUrl(originalUrl);


        EventMessage eventMessage = EventMessage.builder().accountNo(accountNo)
                .content(JsonUtil.obj2Json(request))
                .messageId(IDUtil.geneSnowFlakeID().toString())
                .eventMessageType(EventMessageType.SHORT_LINK_ADD.name())
                .build();


        rabbitTemplate.convertAndSend(rabbitMQConfig.getShortLinkEventExchange(), rabbitMQConfig.getShortLinkAddRoutingKey(),eventMessage);


        return JsonData.buildSuccess();
    }
//短链解析,客户端请求
@GetMapping(path = "/{shortLinkCode}")
    public void dispatch(@PathVariable(name = "shortLinkCode") String shortLinkCode,
                         HttpServletRequest request, HttpServletResponse response) {


        try {
            log.info("短链码:{}", shortLinkCode);
            //判断短链码是否合规
            if (isLetterDigit(shortLinkCode)) {
                //查找短链
                ShortLinkVO shortLinkVO = shortLinkService.parseShortLinkCode(shortLinkCode);
                //判断是否过期和可用
                if (isVisitable(shortLinkVO)) {
                    String originalUrl = CommonUtil.removeUrlPrefix(shortLinkVO.getOriginalUrl());
                    response.setHeader("Location", originalUrl);


                    //302跳转
                    response.setStatus(HttpStatus.FOUND.value());




                } else {


                    response.setStatus(HttpStatus.NOT_FOUND.value());
                    return;
                }
            }
        } catch (Exception e) {
            response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
        }


    }

第二十三章 短链码生成端选择和Lua分布式锁实战

第1集 短链码是生成端选择-生产者端-消费者端方案对比

简介: 短链码是生成端选择-生产者端-消费者端方案对比

  • 短链码是哪里生成?生产者端 还是消费者端

  • 方案一:生产者端生成短链码code

    • 加分布式锁 key=code,配置过期时间(加锁失败则重新生成)
    • 需要查询一次数据库或其他存储源,判断是否存在
    • 发送MQ
      • C端插入
      • B端插入
    • 解分布式锁(锁过期自动解锁)

在这里插入图片描述

方案二:消费者端生成短链码code

  • 生产者发送消息

  • C端生成

    • 加锁key=code
      • 查询数据库,如果存在,则ver版本递增,重新生成短链码
      • 保存数据库
    • 解分布式锁
  • B端生成,

    • 加锁key=code
      • 查询数据库,如果存在,则ver版本递增,重新生成短链码
      • 保存数据库
    • 解分布式锁
第2集 分布式锁知识基础+进阶-可重入锁在分布式下的应用

简介:分布式锁知识基础+进阶-可重入锁在分布式下的应用

  • 不知大家是否还记得,消费者生成短链码,高并发的情况

    • 1)用户A生成短链码AABBCC ,C端先插入,B端还没插入
    • 2)用户B也生成短链码AABBCC ,B端先插入,C端还没插入
    • 3)用户A生成短链码AABBCC ,B端插入
    • 4)用户B生成短链码AABBCC ,C端插入
  • 需要的结果是

    • 1、3可以成功, 2、4可以成功
  • 避免短链码高并发下重复

    • 加锁
      • 本地锁:synchronize、lock等,锁在当前进程内,集群部署下依旧存在问题
      • 分布式锁:redis、zookeeper等实现,虽然还是锁,但是多个进程共用的锁标记,可以用Redis、Zookeeper、Mysql等都可以
        在这里插入图片描述
  • 设计分布式锁应该考虑的东西

    • 排他性
      • 在分布式应用集群中,同一个方法在同一时间只能被一台机器上的一个线程执行
    • 容错性
      • 分布式锁一定能得到释放,比如客户端奔溃或者网络中断
    • 满足可重入、高性能、高可用
    • 注意分布式锁的开销、锁粒度
  • 方案就是加锁

    • 单节点可重入锁

      • 可重入锁: JDK指的是以线程为单位,当一个线程获取对象锁之后,这个线程可以再次获取本对象上的锁,而其他的线程是不可以的,synchronized 和 ReentrantLock 都是可重入锁
    • 分布式下的可重入锁

      • 进程单位,当一个线程获取对象锁之后,其他节点的同个业务线程可以再次获取本对象上的锁
第3集 短链码基于Redis实现分布式锁的坑你是否踩过《上》

简介:基于Redis实现分布式锁的几种坑

  • 实现分布式锁 可以用 Redis、Zookeeper、Mysql数据库这几种 , 性能最好的是Redis且是最容易理解

    • 分布式锁离不开 key - value 设置
    key 是锁的唯一标识,一般按业务来决定命名,比如想要给一种商品的秒杀活动加锁,key 命名为 “seckill_商品ID” 。value就可以使用固定值,比如设置成1。
    短链码可以:short_link:code:xxxx
    
  • 基于redis实现分布式锁,文档:http://www.redis.cn/commands.html#string

    • 加锁 SETNX key value
    setnx 的含义就是 SET if Not Exists,有两个参数 setnx(key, value),该方法是原子性操作
    
    
    如果 key 不存在,则设置当前 key 成功,返回 1;
    
    
    如果当前 key 已经存在,则设置当前 key 失败,返回 0
    
    • 解锁 del (key)
    得到锁的线程执行完任务,需要释放锁,以便其他线程可以进入,调用 del(key)
    
    • 配置锁超时 expire (key,30s)
    客户端奔溃或者网络中断,资源将会永远被锁住,即死锁,因此需要给key配置过期时间,以保证即使没有被显式释放,这把锁也要在一定时间后自动释放
    
    • 综合伪代码
    methodA(){
      String key = "short_link:code:abcdef"
      
      if(setnx(key,1== 1{
          expire(key,30,TimeUnit.MILLISECONDS)
          try {
              //做对应的业务逻辑
          } finally {
              del(key)
          }
      }else{
        //睡眠100毫秒,然后自旋调用本方法
        methodA()
      }
    }
    
    • 存在哪些问题,大家自行思考下
第4集 短链码基于Redis实现分布式锁的坑你是否踩过《下》

简介:短链码基于Redis实现分布式锁的坑你是否踩过

  • 存在什么问题?

    • 多个命令之间不是原子性操作,如setnxexpire之间,如果setnx成功,但是expire失败,且宕机了,则这个资源就是死锁
    使用原子命令:设置和配置过期时间  setnx / setex
    如: set key 1 ex 30 nx
    java代码里面 
    
    
    String key = "short_link:code:abcdef"
    redisTemplate.opsForValue().setIfAbsent(key,1,30,TimeUnit.MILLISECONDS)
    
    • 看业务应用情况还有更多问题,可以看Redis6课程 或者 第一个高并发大课
      • 业务超时,如何避免其他线程勿删
      • 业务执行时间过长,如何实现锁的自

之前说的方案二,消费者端生成短链码code

  • 那C端或者B端其中一个加锁成功后,另外一个怎么加锁?

  • 答案:通过value判断是否是同个账号,如果是则认为是加锁成功

  • 即下面步骤

    • C端生成

    • 加锁key=code,value=account

      • 查询数据库,如果存在,则ver版本递增,重新生成短链码
      • 保存数据库
    • 解分布式锁(锁过期自动解锁)

    • B端生成

      • 加锁key=code,value=account
      • 查询数据库,如果存在,则ver版本递增,重新生成短链码
      • 保存数据库
      • 解分布式锁(锁过期自动解锁)

在这里插入图片描述

  • 流程:加锁的方式需要保证原子性
    • 先判断是否有,如没这个key,则设置key-value,配置过期时间,加锁成功
    • 如果有这个key,判断value是否是同个账号,是同个账号则返回加锁成功
    • 如果不是同个账号则加锁失败
      • 解决方式,配置key过期时间久,比如2~5天
第5集 Lua脚本分布式重入锁+redis原生代码编写

简介:Lua脚本分布式重入锁+redis原生代码编写

  • 前面说了redis做分布式锁存在的问题

    • 核心是保证多个指令原子性,加锁使用setnx setex 可以保证原子性,那解锁使用判断和设置等怎么保证原子性
    • 文档:http://www.redis.cn/commands/set.html
    • 多个命令的原子性:采用 lua脚本+redis, 由于【判断和删除】是lua脚本执行,所以要么全成功,要么全失败
  • 流程

* 先判断是否有,如没这个key,则设置key-value,配置过期时间,加锁成功
* 如果有这个key,判断value是否是同个账号,是同个账号则返回加锁成功
* 如果不是同个账号则加锁失败
  • 代码
//key1是短链码,ARGV[1]是accountNo,ARGV[2]是过期时间
String script = "if redis.call('EXISTS',KEYS[1])==0 then redis.call('set',KEYS[1],ARGV[1]); redis.call('expire',KEYS[1],ARGV[2]); return 1;" +
                " elseif redis.call('get',KEYS[1]) == ARGV[1] then return 2;" +
                " else return 0; end;";


Long result = redisTemplate.execute(new
                DefaultRedisScript<>(script, Long.class), Arrays.asList(code), value,100);
  • 加入redis配置
#-------redis连接配置-------
spring.redis.client-type=jedis
spring.redis.host=120.79.150.146
spring.redis.password=xdclass.net
spring.redis.port=6379
spring.redis.jedis.pool.max-active=100
spring.redis.jedis.pool.max-idle=100
spring.redis.jedis.pool.min-idle=100
spring.redis.jedis.pool.max-wait=60000
第6集 短码服务冗余双写-B端+C端分布式锁代码整合

简介:短码服务冗余双写-B端+C端分布式锁代码整合

  • 整合编码实战

第二十四章 短链服务-冗余双写B端分库分表和链路测试

第1集 GroupCodeMapping表分库分表配置实战

简介: GroupCodeMapping表分库分表配置实战

  • 数据量预估
    • 首年日活用户: 10万
    • 首年日新增短链数据:10万*50 = 500万
    • 年新增短链数:500万 * 365天 = 18.2亿
    • 往高的算就是100亿,支撑3年
  • 分库分表策略
    • 分库分表
      • 8个库, 每个库128个表,总量就是 1024个表
      • 本地开发 2库,每个库2个表
    • 分片键:
      • 分库PartitionKey:account_no
      • 分表PartitionKey:group_id
  • 接口访问量
    • C端解析,访问量大
    • B端查询,访问量少,单个表的存储数据可以多点
  • 配置


##---------- 组+短链码mapping表,策略:分库+分表--------------
# 先进行水平分库,然后再水平分表, 水平分库策略,行表达式分片
spring.shardingsphere.sharding.tables.group_code_mapping.database-strategy.inline.sharding-column=account_no
spring.shardingsphere.sharding.tables.group_code_mapping.database-strategy.inline.algorithm-expression=ds$->{account_no % 2}


# 分表策略+行表达式分片
spring.shardingsphere.sharding.tables.group_code_mapping.actual-data-nodes=ds$->{0..1}.group_code_mapping_$->{0..1}
spring.shardingsphere.sharding.tables.group_code_mapping.table-strategy.inline.sharding-column=group_id
spring.shardingsphere.sharding.tables.group_code_mapping.table-strategy.inline.algorithm-expression=group_code_mapping_$->{group_id % 2}


第2集 短链服务-冗余双写架构全链路测试实战

简介: 短链服务-冗余双写架构全链路测试实战

  • 全链路测试
    • 数据库检查
  • 创建短链
{
  "groupId":1468878230818746370,
  "title":"全链路测试测试标题",
  "originalUrl":"https://baidu.com",
  "domainId":1,
  "domainType":"OFFICIAL",
  "expired":-1
}
第3集 短链服务-B端接口-分页查找短链开发实战

简介: 短链服务-B端接口-分页查找短链开发实战

  • 分页查找某个分组下的短链数据
@Data
public class ShortLinkPageRequest {


    private int page;


    private int size;


    private long groupId;
}


    /**
     * 分页查找短链
     *
     * @return
     */
    @RequestMapping("page")
    public JsonData pageShortLinkByGroupId(@RequestBody ShortLinkPageRequest request) {


        Map<String, Object> pageResult = shortLinkService.pageShortLinkByGroupId(request);


        return JsonData.buildSuccess(pageResult);
    }
  • 注意点

    • IDEA可能有缓存,导致分库分表不生效,mvn clean清理下
  • 删除标记位增加

    • 解析
    • 查找

第二十五章 短链服务-冗余双写架构删除和更新开发实战

第1集 短链服务-冗余双写架构举一反三的能力应用

简介: 冗余双写架构举一反三的能力应用

  • 完成了短链接口的新增,采用了冗余双写的方式
  • 那其他接口呢
    • 删除
    • 更新

在这里插入图片描述

第2集 短链服务-删除和更新Controller层开发实战

简介: 短链服务-删除和更新Controller层开发实战

  • 删除接口
    • controller
    • service
      • 构建消息
@Data
public class ShortLinkDelRequest {


    /**
     * 组
     */
    private Long groupId;


    /**
     * groupCodeMapping映射id
     */
    private Long mappingId;


    /**
     * 短链码
     */
    private String code;
}
  • 更新接口
    • controller
    • service
      • 构建消息
public class ShortLinkUpdateRequest {


    /**
     * 组
     */
    private Long groupId;


    /**
     * groupCodeMapping映射id
     */
    private Long mappingId;


    /**
     * 短链码
     */
    private String code;


    /**
     * 短链标题
     */
    private String title;


    /**
     * 域名id
     */
    private Long domainId;


    /**
     * 域名类型
     */
    private String domainType;


}
  • 消息类型
public enum  EventMessageType {
    /**
     * 短链创建
     */
    SHORT_LINK_ADD,
    /**
     * 短链创建 C端
     */
    SHORT_LINK_ADD_LINK,
    /**
     * 短链创建 B端
     */
    SHORT_LINK_ADD_MAPPING,
    /**
     * 更新创建
     */
    SHORT_LINK_UPDATE,
    /**
     * 更新 C端
     */
    SHORT_LINK_UPDATE_API,
    /**
     * 更新 B端
     */
    SHORT_LINK_UPDATE_MAPPING,
    /**
     * 删除
     */
    SHORT_LINK_DEL,
    /**
     * 删除 C端
     */
    SHORT_LINK_DEL_API,
    /**
     * 删除 B端
     */
    SHORT_LINK_DEL_MAPPING,


}
第3集 冗余双写MQ实现-删除短链-交换机和队列绑定配置实战

简介: 冗余双写MQ架构实现-删除短链-交换机和队列绑定配置讲解

  • 删除短链MQ架构图
  • 更新短链MQ架构图
    在这里插入图片描述
第5集 短链服务-删除和更新模块发送MQ消息验证

简介: 短链服务-删除和更新模块发送MQ消息验证

  • 删除 发送消息

  • 更新 发送消息

  • RabbitMQ控制台查看
    private String title;

    /**

    • 域名id
      */
      private Long domainId;

    /**

    • 域名类型
      */
      private String domainType;

}


 

- 消息类型

```java
public enum  EventMessageType {
    /**
     * 短链创建
     */
    SHORT_LINK_ADD,
    /**
     * 短链创建 C端
     */
    SHORT_LINK_ADD_LINK,
    /**
     * 短链创建 B端
     */
    SHORT_LINK_ADD_MAPPING,
    /**
     * 更新创建
     */
    SHORT_LINK_UPDATE,
    /**
     * 更新 C端
     */
    SHORT_LINK_UPDATE_API,
    /**
     * 更新 B端
     */
    SHORT_LINK_UPDATE_MAPPING,
    /**
     * 删除
     */
    SHORT_LINK_DEL,
    /**
     * 删除 C端
     */
    SHORT_LINK_DEL_API,
    /**
     * 删除 B端
     */
    SHORT_LINK_DEL_MAPPING,


}
第3集 冗余双写MQ实现-删除短链-交换机和队列绑定配置实战

简介: 冗余双写MQ架构实现-删除短链-交换机和队列绑定配置讲解

  • 删除短链MQ架构图
  • 更新短链MQ架构图

[外链图片转存中…(img-1sasDsYr-1723078707796)]

第5集 短链服务-删除和更新模块发送MQ消息验证

简介: 短链服务-删除和更新模块发送MQ消息验证

  • 删除 发送消息
  • 更新 发送消息
  • RabbitMQ控制台查看

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1991455.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

古彝文——唯一存活的世界六大古文字

关注我们 - 数字罗塞塔计划 - 早在五千年前&#xff0c;彝族的先祖就发明了十月太阳历&#xff0c;成为中华文明的重要创造者之一&#xff1b;同时&#xff0c;彝族的先祖也创制了古彝文&#xff0c;开创了独具特色的彝族文化。古彝文也被称为古夷文、传统彝文&#xff0c;是相…

Unity补完计划 之 动态控制TileMap

本文仅作笔记学习和分享&#xff0c;不用做任何商业用途 本文包括但不限于unity官方手册&#xff0c;unity唐老狮等教程知识&#xff0c;如有不足还请斧正 1.TileMap &TileBase Unity - Scripting API: Tilemap &#xff0c;看手册内容太多了故介绍几个常用的公共方法 首…

一个IT能拖垮整个公司?你若不信,看完此文再来评论

看到文章的标题&#xff0c;你也许会心生疑惑&#xff1a;一个IT真的能拖垮整个公司吗&#xff1f;也可能会觉得我根本就是在哗众取宠、博人眼球。 而我要说&#xff0c;在特定的条件下&#xff0c;这真的不夸张&#xff0c;你若不信&#xff0c;且听我娓娓道来&#xff0c;看完…

java maven项目如何分析循环依赖并使用maven helper插件排查排除依赖

文章目录 java maven项目如何分析循环依赖并使用maven helper插件排查排除依赖分析项目依赖插件Maven Helper找到并排除循环的依赖 java maven项目如何分析循环依赖并使用maven helper插件排查排除依赖 分析项目依赖 选择检测整个项目 查看红色的模块&#xff0c;都是有循环依…

问卷星无法选择复制

删除<link rel"stylesheet" href"//image.wjx.cn/joinnew/css/jqmobo.css?v5187">

【信创】Linux如何增加与删除交换分区 _ 统信 _ 麒麟 _ 中科方德

原文链接&#xff1a;信创】Linux如何增加与删除交换分区 | 统信 | 麒麟 | 中科方德 Hello&#xff0c;大家好啊&#xff01;今天给大家带来一篇关于在信创终端操作系统上如何增加与删除交换分区的文章。交换分区&#xff08;Swap&#xff09;在Linux系统中扮演着重要角色&…

思特威正式发布子品牌飞凌微,首发产品定位智驾视觉处理

2024年8月8日&#xff0c;中国上海 — 思特威&#xff08;上海&#xff09;电子科技股份有限公司&#xff08;股票简称&#xff1a;思特威&#xff0c;股票代码&#xff1a;688213&#xff09;正式发布全资子公司品牌——飞凌微电子&#xff08;Flyingchip™&#xff0c;以下简…

工具学习_CAPA a ATTCK

随着网络威胁的日益复杂和多样化&#xff0c;恶意软件的分析与识别成为安全领域的重要挑战。在这个背景下&#xff0c;静态分析技术成为了对抗恶意软件的有效手段。CAPA 作为一款强大的静态分析工具&#xff0c;能够帮助分析师快速提取恶意软件的静态特征&#xff0c;而 ATT&am…

无线领夹麦克风和有线哪个好?求知无线领夹麦哪个牌子好?

如今&#xff0c;自媒体行业蓬勃发展&#xff0c;音频设备作为创作过程中不可或缺的一部分&#xff0c;越来越受到重视。无线领夹麦克风因其出色的性能和便携性&#xff0c;逐渐成为市场上的热门产品。购买无线领夹麦克风已经成为许多创作者的共识。然而&#xff0c;面对市面上…

自动驾驶系列—图像到IPM:深入解析IMP投影变换技术

&#x1f31f;&#x1f31f; 欢迎来到我的技术小筑&#xff0c;一个专为技术探索者打造的交流空间。在这里&#xff0c;我们不仅分享代码的智慧&#xff0c;还探讨技术的深度与广度。无论您是资深开发者还是技术新手&#xff0c;这里都有一片属于您的天空。让我们在知识的海洋中…

第十九天(2024.8.7)Vue Element-plus

1.Vue 1.创建vue文件 1.创建一个文件夹来存储vue文件 我在D盘下创建了一个EasyVue文件夹来存储vue文件 2.在控制台中输入 如果在控制台中按下面步骤成功不了的话&#xff0c;尝试&#xff1a;1.用管理员身份运行控制台 2.关闭防火墙 3.打开编码工具&#xff08;Visual St…

易基因:干旱胁迫下的作物DNA甲基化动态变化 | 植物抗逆

大家好&#xff0c;这里是专注表观组学十余年&#xff0c;领跑多组学科研服务的易基因。 干旱&#xff08;Drought&#xff09;会对植物的生长、发育和生产力造成严重损害&#xff0c;是最具危害性的环境因素之一。植物已经进化出复杂的调控网络和干旱胁迫的抗性策略。作为一种…

终于有人把客户成功讲明白了

作者&#xff1a;沈建明 对ToB企业来说&#xff0c;只有客户成功才能带来持久增长&#xff0c;在SaaS企业下行大背景下&#xff0c;客户成功是唯一的救命稻草。大家是不是都听过这样的说法&#xff1f; ToB和SaaS企业的老客户贡献对于企业至关重要。因为获取新客户的成本是留…

Pycharm中重命名项目之后切换虚拟环境

Pycharm中重命名项目之后切换虚拟环境 场景 在Pycharm里面Rename Project/Directory之后&#xff0c;通常需要切换虚拟环境。 步骤 # 退出当前虚拟环境 deactivate # 删除旧的虚拟环境 .venv # 新建新的虚拟环境 python -m venv .venv # 切换到新的工程目录 cd E:\Bigdata\…

HexView 刷写文件脚本处理工具-基本功能介绍(六)-导出MIME/BIN/FIAT/FORD

导出MIME编码数据 这个选项将数据文件导出为MIME编码格式,并使用BASE64编码。 导出二进制数据 此选项会将所有数据内容按照它们出现的顺序写入一个二进制文件。 导出二进制块数据 这个选项将数据导出到一个二进制文件中。但是,如果内部数据文件包含多个块,数据将被写…

Qt 跨平台APP单实例运行实现

一.调用方法 支持coreApplication和简单的application两种继承&#xff1a; 二.源码地址&#xff1a; SingleApp: Qt 单实例实现

代码随想录打卡第四十九天

代码随想录–单调栈部分 day 49 单调栈第二天 文章目录 代码随想录--单调栈部分一、力扣42--接雨水二、力扣84--柱状图中最大的矩形 一、力扣42–接雨水 代码随想录题目链接&#xff1a;代码随想录 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列…

HexView 刷写文件脚本处理工具-基本功能介绍(十)-数据自动对齐与填充

文件 在二进制文件被编译出来后,如果没有在链接文件中进行填充的话,通常都是分段落的,还有一些不需要的信息在里面,如果没有对齐的话可以用hexview进行对齐。 一般还会要求进行数据的填充,这样的话释放的刷写文件就是一个整体的段落。 数据对齐 数据对齐操作是基于块的…

使用WPF将window 添加到TabControl里面的方法

首先 1.window 不能添加到其他控件中&#xff0c;原因是他是最高级的。。 在window usercontrol&#xff0c;以及page&#xff0c;frame 基本都遵循这个道理&#xff0c;可以添加的则是 除window以外的其他窗体。 2.添加到TabControl 下面的TabItem 控件添加usercontrl我遇到的…

AMEYA360:灵动微电子MM32SPIN0230为核,打造All-in-One智能功率模块

全新电动牙刷市场、小风机市场革新性选择MM32SPIN028C即将发布! 在个人护理日益受到重视的今天&#xff0c;电动牙刷市场正迎来前所未有的增长&#xff0c;而手持风扇也在消费电子领域迅速崛起。作为位居前列的的中国本土32位MCU供应商&#xff0c;灵动微电子宣布将在近期与合作…