海量数据处理商用短链接生成器平台 - 9
第二十六章 短链服务-冗余双写架构删除和更新消费者开发实战
第1集 冗余双写架构-更新短链消费者开发实战
简介: 短链服务-更新短链-消费者开发实战
具体步骤见代码
第2集 冗余双写架构-更新短链消费者链路测试
简介: 冗余双写架构-更新短链消费者链路测试
具体步骤见代码
第3集 冗余双写架构-删除短链消费者开发实战
简介: 短链服务-删除短链-消费者开发实战
具体步骤见代码
第4集 冗余双写架构-删除短链消费者链路测试和越权修复
简介: 冗余双写架构-删除短链消费者链路测试
-
对数据库操作的时候,一定要防止越权
- 一个是直接RPC调用
- 一个是通过MQ调用
具体步骤见代码
第5集 冗余双写架构-短链服务开发总结
简介: 冗余双写架构-短链服务开发总结
- 短链服务器CRUD
- 冗余双写架构
- 异常队列
- 最终一致性
第二十七章 流量包商品服务需求和库表讲解
第1集 流量包商品服务-业务需求讲解
简介: 流量包商品服务需求讲解
-
流量包需求讲解
- 百度短链案例 https://dwz.cn/console/price
-
流量包商品模型
- 每个套餐都是一个虚拟商品,没库存限制
- 免费版是新用户注册即可获得
- 不同的商品每天限制的创建的条数不一样
- 用户可以叠加使用多个流量包
-
业务难点
- 流量包购买支付(P2)
- 流量包管理
- 免费流量包管理(P1)
- 付费流量包管理(P1)
- 短链业务-流量包业务联动(P1)
第2集 流量包商品服务-数据库表介绍和实体类生成
简介: 流量包商品服务-数据库表介绍
- 数据库表介绍
CREATE TABLE `product` (`id` bigint NOT NULL,`title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '商品标题',`detail` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '详情',`img` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '图片',`level` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '产品层级:FIRST青铜、SECOND黄金、THIRD钻石',`old_amount` decimal(16,0) DEFAULT NULL COMMENT '原价',`amount` decimal(16,0) DEFAULT NULL COMMENT '现价',`plugin_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '工具类型 short_link、qrcode',`day_times` int DEFAULT NULL COMMENT '日次数:短链类型',`total_times` int DEFAULT NULL COMMENT '总次数:活码才有',`valid_day` int DEFAULT NULL COMMENT '有效天数',`gmt_modified` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,`gmt_create` datetime DEFAULT CURRENT_TIMESTAMP,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
- 数据库创建
- 插入初始化数据
INSERT INTO `dcloud_shop`.`product` (`id`, `title`, `detail`, `img`, `level`, `old_amount`, `amount`, `plugin_type`, `day_times`, `total_times`, `valid_day`, `gmt_modified`, `gmt_create`) VALUES (1, '青铜会员-默认', '数据查看支持||日生成短链{{dayTimes}}次||限制跳转50次||默认域名', NULL, 'FIRST', 19, 0, 'SHORT_LINK', 2, NULL, 1, '2021-10-14 17:33:44', '2021-10-11 10:49:35');INSERT INTO `dcloud_shop`.`product` (`id`, `title`, `detail`, `img`, `level`, `old_amount`, `amount`, `plugin_type`, `day_times`, `total_times`, `valid_day`, `gmt_modified`, `gmt_create`) VALUES (2, '黄金会员-月度', '数据查看支持||日生成短链{{dayTimes}}次||限制不限制||默认域名', NULL, 'SECOND', 99, 1, 'SHORT_LINK', 5, NULL, 30, '2021-10-19 14:36:28', '2021-10-11 10:57:47');INSERT INTO `dcloud_shop`.`product` (`id`, `title`, `detail`, `img`, `level`, `old_amount`, `amount`, `plugin_type`, `day_times`, `total_times`, `valid_day`, `gmt_modified`, `gmt_create`) VALUES (3, '黑金会员-月度', '数据查看支持||日生成短链{{dayTimes}}次||限制不限制||自定义域名', NULL, 'THIRD', 199, 2, 'SHORT_LINK', 8, NULL, 30, '2021-10-19 14:36:30', '2021-10-11 11:01:13');
- MybatisPlus实体类生成
第3集 流量包商品服务-项目基本骨架创建
简介: 流量包商品服务-项目基本骨架创建
- 配置文件增加和默认库表配置
server.port=8005
spring.application.name=dcloud-shop#服务注册发现
spring.cloud.nacos.discovery.server-addr=120.79.150.146:8848
spring.cloud.nacos.discovery.username=nacos
spring.cloud.nacos.discovery.password=nacosspring.shardingsphere.datasource.names=ds1
spring.shardingsphere.datasource.ds0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds0.jdbc-url=jdbc:mysql://120.79.150.146:3306/dcloud_shop?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
spring.shardingsphere.datasource.ds0.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.ds0.username=root
spring.shardingsphere.datasource.ds0.password=class.net168spring.shardingsphere.datasource.ds0.connectionTimeoutMilliseconds=30000
spring.shardingsphere.datasource.ds0.idleTimeoutMilliseconds=60000
spring.shardingsphere.datasource.ds0.maintenanceIntervalMilliseconds=30000
spring.shardingsphere.datasource.ds0.maxLifetimeMilliseconds=1800000
spring.shardingsphere.datasource.ds0.maxPoolSize=50
spring.shardingsphere.datasource.ds0.minPoolSize=50spring.shardingsphere.props.sql.show=truelogging.level.root=INFO
- 启动类配置
- controller-service-manager层建立
第4集 流量包商品服务-商品列表和详情接口链路开发
简介: 流量包商品服务-商品列表和详情接口链路开发
- 商品列表接口开发
- 商品详情接口开发
第二十八章 流量包订单模块需求讲解和库表介绍
第1集 流量包订单模块-业务需求讲解
简介: 流量包订单模块-业务需求讲解
- 流量包订单需求讲解
- 需求
- 支持叠加购买
- 效果:1个流量包支持1天创建50条,如果买了两个则支持1天创建100条
- 支持多渠道支付
- 支付宝、微信等
- 开发对接微信V3最新版支付,支付宝支付的参考第一个高并发项目大课
- V2版微信支付对接可以看
- https://detail.tmall.com/item.htm?id=649570556856
- PC端支付宝支付可以看
- https://detail.tmall.com/item.htm?id=646525336722
- 支持叠加购买
第2集 流量包订单-数据库表介绍和实体类生成
简介: 流量包订单-数据库表介绍和实体类生成
- 数据库表
CREATE TABLE `product_order` (`id` bigint NOT NULL,`product_id` bigint DEFAULT NULL COMMENT '订单类型',`product_title` varchar(64) DEFAULT NULL COMMENT '商品标题',`product_amount` decimal(16,2) DEFAULT NULL COMMENT '商品单价',`product_snapshot` varchar(2048) DEFAULT NULL COMMENT '商品快照',`buy_num` int DEFAULT NULL COMMENT '购买数量',`out_trade_no` varchar(64) DEFAULT NULL COMMENT '订单唯一标识',`state` varchar(11) DEFAULT NULL COMMENT 'NEW 未支付订单,PAY已经支付订单,CANCEL超时取消订单',`create_time` datetime DEFAULT NULL COMMENT '订单生成时间',`total_amount` decimal(16,2) DEFAULT NULL COMMENT '订单总金额',`pay_amount` decimal(16,2) DEFAULT NULL COMMENT '订单实际支付价格',`pay_type` varchar(64) DEFAULT NULL COMMENT '支付类型,微信-银行-支付宝',`nickname` varchar(64) DEFAULT NULL COMMENT '账号昵称',`account_no` bigint DEFAULT NULL COMMENT '用户id',`del` int DEFAULT '0' COMMENT '0表示未删除,1表示已经删除',`gmt_modified` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',`gmt_create` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',`bill_type` varchar(32) DEFAULT NULL COMMENT '发票类型:0->不开发票;1->电子发票;2->纸质发票',`bill_header` varchar(200) DEFAULT NULL COMMENT '发票抬头',`bill_content` varchar(200) DEFAULT NULL COMMENT '发票内容',`bill_receiver_phone` varchar(32) DEFAULT NULL COMMENT '发票收票人电话',`bill_receiver_email` varchar(200) DEFAULT NULL COMMENT '发票收票人邮箱',PRIMARY KEY (`id`),UNIQUE KEY `uk_query` (`out_trade_no`,`account_no`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
- 数据库实体类生成
第3集 流量包订单-数据库表分库分表讲解和配置
简介: 流量包订单-数据库表分库分表讲解和配置
- 业务需求
- 用户查看自己的订单列表
- 数据存储需求(都是前期规划,上线前可以调整分库分表策略和数量)
- 未来2年,短链平台累计5百万用户
- 付费流包记录:
- 一个用户10条/年,总就是5千万条/年,两年是1亿
- 单表不超过1千万数据,需要分10张表
- 进一步延伸,进行水平分表,比如 2张表、4张表、8张 表、16张表
- 分表数:线上分16张表,本地分2张表即可
- 分片key
- account_no作为partitionKey
#----------配置默认数据库,比如短链域名,不分库分表--------------
spring.shardingsphere.sharding.default-data-source-name=ds0
#默认id生成策略
spring.shardingsphere.sharding.default-key-generator.column=id
spring.shardingsphere.sharding.default-key-generator.type=SNOWFLAKE
spring.shardingsphere.sharding.default-key-generator.props.worker.id=${workerId}# 指定product_order表的数据分布情况,配置数据节点,行表达式标识符使用 ${...} 或 $->{...},但前者与 Spring 本身的文件占位符冲突,所以在 Spring 环境中建议使用 $->{...}
spring.shardingsphere.sharding.tables.product_order.actual-data-nodes=ds0.product_order_$->{0..1}
#水平分表策略+行表达式分片
spring.shardingsphere.sharding.tables.product_order.table-strategy.inline.algorithm-expression=product_order_$->{ account_no % 2 }
spring.shardingsphere.sharding.tables.product_order.table-strategy.inline.sharding-column=account_no
第4集 流量包订单-Manager层CRUD接口开发
简介: 流量包订单-Manager层CRUD接口开发
- 开发Manager层CRUD接口
第5集 流量包订单-基础分表Manager层单元测试
简介: 流量包订单-基础分表Manager层单元测试
- 单元测试
第二十九章 流量包商品服务-下单模块开发和订单防重提交
第1集 流量包商品服务-订单controller相关接口开发
简介: 商品服务-订单controller相关接口开发
- 分页接口开发
- 订单状态查询接口(扫码支付-订单状态检查)
- 下单接口(controller骨架)
- 支付宝支付返回HTML
- 微信支付返回JSON
第2集 流量包商品服务-流量包下单模块链路流程分析讲解
简介: 商品服务-订单下单模块链路流程分析讲解
- 不涉及到商品库存管理
- 防重提交(重点)
- 获取最新的流量包价格
- 订单验价
- 如果有优惠券或者其他抵扣
- 验证前端显示和后台计算价格
- 创建订单对象保存数据库
- 发送延迟消息-用于自动关单(重点)
- 创建支付信息-对接三方支付(重点)
- 回调更新订单状态(重点)
- 支付成功创建流量包(重点)
第3集 流量包商品服务-下单接口链路骨架开发
简介: 商品服务-流量包下单接口链路骨架开发
- 业务流程
- 重防提交(TODO)
- 获取最新的流量包价格
- 订单验价
- 如果有优惠券或者其他抵扣
- 验证前端显示和后台计算价格
- 创建订单对象保存数据库
- 发送延迟消息-用于自动关单(TODO)
- 创建支付信息-对接三方支付(TODO)
- 回调更新订单状态(TODO)
- 支付成功创建流量包(TODO)
- 代码开发
第4集 流量包商品服务-避免重复下单你能想到几种方式
简介:避免复下单常见解决方案
-
开发的项目中可能会出现下面这些情况:
- 前端下单按钮复点击导致订单创建多次
- 网速等原因造成页面卡顿,用户重复刷新提交请求
- 黑客或恶意用户使用postman等http工具重复恶意提交表单
-
问题
- 会导致表单重复提交,造成数据重复或者错乱
- 核心接口的请求增加,消耗服务器负载,严重甚至会造成服务器宕机
-
因此核心接口需要做防重提交,你能想到几种方式
-
方式一:前端JS控制点击次数,屏蔽点击按钮无法点击
- 前端可以被绕过,前端有限制,后端也需要有限制
-
方式二:数据库或者其他存储增加唯一索引约束
- 需要想出满足业务需求的唯一索引约束,比如注册的手机号唯一
-
方式三:服务端token令牌方式
- 下单前先获取令牌-存储redis 下单时一并把token提交并检验和删除-lua脚本
- 分布式情况下,采用Lua脚本进行操作
String script = "if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end";
-
- 方式三 是大家采用的最多的,那有没更加优雅的方式呢?
- 采用自定义注解,也有多种方式
第三十章 流量包商品服务-多场景自定义注解防重提交实战
第1集 java核心知识-教你掌握自定义注解
简介:java核心知识-自定义注解
- Annotation(注解)
- 从JDK 1.5开始, Java增加了对元数据(MetaData)的支持,也就是 Annotation(注解)。
- 注解其实就是代码里的特殊标记,它用于替代配置文件
- 常见的很多 @Override、@Deprecated等
- 什么是元注解
- 注解的注解,比如当我们需要自定义注解时
- 会需要一些元注解(meta-annotation),如**@Target和@Retention**
- java内置4种元注解
- @Target 表示该注解用于什么地方
- ElementType.CONSTRUCTOR 用在构造器
- ElementType.FIELD 用于描述域-属性上
- ElementType.METHOD 用在方法上
- ElementType.TYPE 用在类或接口上
- ElementType.PACKAGE 用于描述包
- @Retention 表示在什么级别保存该注解信息
- RetentionPolicy.SOURCE 保留到源码上
- RetentionPolicy.CLASS 保留到字节码上
- RetentionPolicy.RUNTIME 保留到虚拟机运行时(最多,可通过反射获取)
- @Documented 将此注解包含在 javadoc 中
- @Inherited 是否允许子类继承父类中的注解
- @Target 表示该注解用于什么地方
- @interface
- 用来声明一个注解,可以通过default来声明参数的默认值
- 自定义注解时,自动继承了java.lang.annotation.Annotation接口
- 通过反射可以获取自定义注解
第2集 AOP+自定义注解-接口防重提交多场景设计
简介: AOP+自定义注解接口防重提交多场景设计
- 防重提交方式
- token令牌方式
- ip+类+方法方式
- 利用AOP
- Aspect Oriented Program 面向切面编程, 在不改变原有逻辑上增加额外的功能
- AOP思想把功能分两个部分,分离系统中的各种关注点
- 好处
- 减少代码侵入,解耦
- 可以统一处理横切逻辑
- 方便添加和删除横切逻辑
- 业务流程
- 自定义注解
import java.lang.annotation.*;@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RepeatSubmit {/*** 加锁过期时间,默认是5秒* @return*/long lockTime() default 5;/*** 默认限制类型,是方法参数* @return*/Type limitType() default Type.PARAM;/*** 两种类型,token 或者 param*/enum Type{ PARAM , TOKEN};
}
第3集 订单防重提交-自定义注解开发实战-Token令牌方式
简介:订单防重提交-自定义注解开发实战-Token令牌方式
- 新增redis配置
#-------redis连接配置-------
spring.redis.client-type=jedis
spring.redis.host=120.79.150.146
spring.redis.password=class.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
- 编写接口获取令牌
@Autowiredprivate StringRedisTemplate redisTemplate;@GetMapping("token")public JsonData getToken(){LoginUser loginUser = LoginInterceptor.threadLocal.get();String token = CommonUtil.getStringNumRandom(32);//"order:submit:%s:%s"String key = String.format(RedisKey.SUBMIT_ORDER_TOKEN_KEY, loginUser.getAccountNo(),requestToken);redisTemplate.opsForValue().set(key, "1", 30, TimeUnit.MINUTES);return JsonData.buildSuccess(token);}
- 定义切面类-开发解析器
/*** 定义 @Pointcut注解表达式,* 方式一:@annotation:当执行的方法上拥有指定的注解时生效(我们采用这)* 方式二:execution:一般用于指定方法的执行** @param repeatSubmit*/@Pointcut("@annotation(repeatSubmit)")public void pointcutNoRepeatSubmit(RepeatSubmit repeatSubmit) {}/*** 环绕通知, 围绕着方法执行* @Around 可以用来在调用一个具体方法前和调用后来完成一些具体的任务。** 方式一:单用 @Around("execution(* net.class.controller.*.*(..))")可以* 方式二:用@Pointcut和@Around联合注解也可以(我们采用这个)*** 两种方式* 方式一:加锁 固定时间内不能重复提交* <p>* 方式二:先请求获取token,这边再删除token,删除成功则是第一次提交** @param joinPoint* @param noRepeatSubmit* @return* @throws Throwable*/@Around("pointcutNoRepeatSubmit(noRepeatSubmit)")public Object around(ProceedingJoinPoint joinPoint, RepeatSubmit noRepeatSubmit) throws Throwable {HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();boolean res;String type = noRepeatSubmit.limitType().name();if (type.equals(RepeatSubmit.Type.PARAM.name())) {//方式一方法参数 TODO} else {//方式二,令牌形式String requestToken = request.getHeader("request-token");if (StringUtils.isBlank(requestToken)) {throw new BizException(BizCodeEnum.ORDER_CONFIRM_TOKEN_EQUAL_FAIL);}LoginUser loginUser = LoginInterceptor.threadLocal.get();//"order:submit:%s:%s"String key = String.format(RedisKey.SUBMIT_ORDER_TOKEN_KEY, loginUser.getAccountNo(),requestToken);/*** 提交表单的token key* 方式一:不用lua脚本获取再判断,之前是因为 key组成是 order:submit:accountNo, value是对应的token,所以需要先获取值,再判断* 方式二:可以直接key是 order:submit:accountNo:token,然后直接删除成功则完成*/res = stringRedisTemplate.delete(key);}if (!res) {throw new BizException(BizCodeEnum.ORDER_CONFIRM_REPEAT);}System.out.println("目标方法执行前");Object object = joinPoint.proceed();System.out.println("目标方法执行后");return object;}
第4集 Spring里面的AOP常见概念复习巩固
简介:Spring里面的AOP常见概念复习巩固
-
能否解释下AOP里面常见的概念,比如 横切、通知、连接点、切入点、切面 ?
-
横切关注点
- 对哪些方法进行拦截,拦截后怎么处理,这些就叫横切关注点
- 比如 权限认证、日志、事物
-
通知 Advice
- 在特定的切入点上执行的增强处理
- 做啥? 比如你需要记录日志,控制事务 ,提前编写好通用的模块,需要的地方直接调用
- 比如重复提交判断逻辑
- 类型
- @Before前置通知
- 在执行目标方法之前运行
- @After后置通知
- 在目标方法运行结束之后
- @AfterReturning返回通知
- 在目标方法正常返回值后运行
- @AfterThrowing异常通知
- 在目标方法出现异常后运行
- @Around环绕通知
- 在目标方法完成前、后做增强处理 ,环绕通知是最重要的通知类型 ,像事务,日志等都是环绕通知,注意编程中核心是一个ProceedingJoinPoint,需要手动执行 joinPoint.procced()
- @Before前置通知
-
连接点 JointPoint
- 要用通知的地方,业务流程在运行过程中需要插入切面的具体位置,
- 一般是方法的调用前后,全部方法都可以是连接点
- 只是概念,没啥特殊
-
切入点 Pointcut
- 不能全部方法都是连接点,通过特定的规则来筛选连接点, 就是Pointcut,选中那几个你想要的方法
- 在程序中主要体现为书写切入点表达式(通过通配、正则表达式)过滤出特定的一组 JointPoint连接点
- 过滤出相应的 Advice 将要发生的joinpoint地方
-
切面 Aspect
- 通常是一个类,里面定义 切入点+通知 , 定义在什么地方; 什么时间点、做什么事情
- 通知 advice指明了时间和做的事情(前置、后置等)
- 切入点 pointcut 指定在什么地方干这个事情
- web接口设计中,web层->网关层->服务层->数据层,每一层之间也是一个切面,对象和对象,方法和方法之间都是一个个切面
-
目标 target
- 目标类,真正的业务逻辑,可以在目标类不知情的条件下,增加新的功能到目标类的链路上
-
织入 Weaving
- 把切面(某个类)应用到目标函数的过程称为织入
-
第5集 订单防重提交-自定义注解-Token方式效果验证
简介:订单防重提交-自定义注解开发-Token式效果验证
- 下单接口增加注解
@RepeatSubmit(limitType = RepeatSubmit.Type.TOKEN)
- 获取令牌
- 其他bug修复
第6集 订单防重提交-自定义注解开发实战-参数式
简介:订单防重提交-自定义注解开发实战
- 开发配置
//方式一方法参数long lockTime = noRepeatSubmit.lockTime();String ip = CommonUtil.getIpAddr(request);//获取注解MethodSignature signature = (MethodSignature) joinPoint.getSignature();Method method = signature.getMethod();//目标类、方法String className = method.getDeclaringClass().getName();String name = method.getName();String key = String.format("%s#%s#%s#%s",accountNo,ip, className, name);log.info("key={}", key);// 分布式锁 TODO, 直接设置key配置过期时间也行
- 分布式锁几种实现
- Redis+Lua脚本
- Redission
- 直接redis操作
使用原子命令:设置和配置过期时间 setnx / setex
如: set key 1 ex 30 nxjava代码里面
redisTemplate.opsForValue().setIfAbsent(key,1,30,TimeUnit.MILLISECONDS)
第7集 Redission分布式锁介绍和配置引入
简介:Redission分布式锁介绍和配置引入
- Redission介绍
- 是一个在Redis的基础上实现的Java驻内存数据网格,支持多样Redis配置支持、丰富连接方式、分布式对象、分布式集合、分布式锁、分布式服务、多种序列化方式、三方框架整合
- Redisson底层采用的是Netty 框架
- 官方文档:https://github.com/redisson/redisson
- 配置加入
聚合工程锁定版本,common项目添加依赖(多个服务都会用到分布式锁)<!--分布式锁-->
<dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.10.1</version>
</dependency>
- 代码配置
@Value("${spring.redis.host}")private String redisHost;@Value("${spring.redis.port}")private String redisPort;@Value("${spring.redis.password}")private String redisPwd;/*** 配置分布式锁的redisson* @return*/@Beanpublic RedissonClient redissonClient(){Config config = new Config();//单机方式config.useSingleServer().setPassword(redisPwd).setAddress("redis://"+redisHost+":"+redisPort);//集群//config.useClusterServers().addNodeAddress("redis://192.31.21.1:6379","redis://192.31.21.2:6379")RedissonClient redissonClient = Redisson.create(config);return redissonClient;}/*** 集群模式* 备注:可以用"rediss://"来启用SSL连接*//*@Beanpublic RedissonClient redissonClusterClient() {Config config = new Config();config.useClusterServers().setScanInterval(2000) // 集群状态扫描间隔时间,单位是毫秒.addNodeAddress("redis://127.0.0.1:7000").addNodeAddress("redis://127.0.0.1:7002");RedissonClient redisson = Redisson.create(config);return redisson;}*/
- 加锁调用
// 分布式锁RLock lock = redissonClient.getLock(key);// 尝试加锁,最多等待2秒,上锁以后5秒自动解锁 [lockTime默认为5s, 可以自定义]res = lock.tryLock(2, lockTime, TimeUnit.SECONDS);
第8集 订单防重提交-自定义注解开发-参数式效果验证
简介:订单防重提交-自定义注解开发-参数式效果验证
-
效果验证
-
两种防重提交,应用场景不一样,也可以更多方式进行防重
-
个人接入微信支付V3版参数示例
- 公众号:appid: wx5beac15ca207c40c
- 商户平台
- 商户号:1601644442
- APIv3密钥:peYcTwRF581UOdaUqoPOeHzJ8FgHgsnJ
- 证书序列号:7064ADC5FE84CA2A3DDE71A692E39602DEB96E61
- 证书文件:本章本集的资料里面(不可用,最新的群公告获取)
Config config = new Config();
config.useClusterServers().setScanInterval(2000) // 集群状态扫描间隔时间,单位是毫秒
.addNodeAddress(“redis://127.0.0.1:7000”)
.addNodeAddress(“redis://127.0.0.1:7002”);
RedissonClient redisson = Redisson.create(config);
return redisson;
}*/
- 加锁调用```java// 分布式锁RLock lock = redissonClient.getLock(key);// 尝试加锁,最多等待2秒,上锁以后5秒自动解锁 [lockTime默认为5s, 可以自定义]res = lock.tryLock(2, lockTime, TimeUnit.SECONDS);
第8集 订单防重提交-自定义注解开发-参数式效果验证
简介:订单防重提交-自定义注解开发-参数式效果验证
-
效果验证
-
两种防重提交,应用场景不一样,也可以更多方式进行防重
-
个人接入微信支付V3版参数示例
- 公众号:appid:
- 商户平台
- 商户号:
- APIv3密钥:
- 证书序列号:
- 证书文件:本章本集的资料里面(不可用,最新的群公告获取)
相关文章:

海量数据处理商用短链接生成器平台 - 9
第二十六章 短链服务-冗余双写架构删除和更新消费者开发实战 第1集 冗余双写架构-更新短链消费者开发实战 简介: 短链服务-更新短链-消费者开发实战 具体步骤见代码 第2集 冗余双写架构-更新短链消费者链路测试 简介: 冗余双写架构-更新短链消费者链…...

从困境到突破,EasyMR 集群迁移助力大数据底座信创国产化
在大数据时代,企业对数据的依赖程度越来越高。然而,随着业务的不断发展和技术的快速迭代,大数据平台的集群迁移已成为企业数据中台发展途中无法回避的需求。在大数据平台发展初期,国内数据中台市场主要以国外开源 CDH、商业化 CDP…...
【Mysql】第十二章 视图特性(概念+使用)
文章目录 一、概念二、使用1.创建视图2.修改视图会影响基表3.修改基表会影响视图4.删除视图 一、概念 视图不能添加索引,也不能有关联的触发器或者默认值。由于视图和基表用的本质是同一份数据,因此对视图的修改会影响到基表,对基表的修改也…...

【颠覆数据处理的利器】全面解读Apache Flink实时大数据处理的引擎-上篇
什么是 Apache Flink? Apache Flink 是一个框架和分布式处理引擎,用于对无界和有界数据流进行有状态计算。Flink 被设计为在所有常见的集群环境中运行,以内存速度和任何规模执行计算。 如何理解无界和有界数据? 无界数据&#…...

【C++】C++11(可变参数模板、lambda表达式、包装器)
文章目录 1. 可变参数模板1.1 介绍1.2 emplace系列接口实现 2. lambda表达式2.1 语法介绍2.2 原理 3. 包装器4. bind 1. 可变参数模板 1.1 介绍 可变参数我们在C语言阶段已经了解过了,C语言中叫做可变参数列表,其中使用 ... 代表可变参数。 C语言中的可…...

矩阵获客时代,云微客让你一个人成就一支队伍
短视频利用大家碎片化的时间让自身得到广泛的应用和发展,因此很多公司纷纷布局短视频赛道。但是一个账号的曝光量有限,并且能够出的爆款视频更是少之又少,这个时候就需要增加账号的数量,布局形成账号矩阵。 做账号矩阵,…...

浅谈基础的图算法——Tarjan求强联通分量算法(c++)
文章目录 强联通分量SCC概念例子有向图的DFS树代码例题讲解[POI2008] BLO-Blockade题面翻译题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 思路AC代码 【模板】割点(割顶)题目背景题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 提示…...

【Godot4自学手册】第四十四节用着色器(shader)实现溶解效果
本小节,我将自学用用着色器(shader)实现溶解效果,最终效果如下: 一、进行shader初始设置 首先我们进入Player场景,选择AnimatedSprite2D节点,在检查器中找到CanvasItem属性,并在M…...

【画流程图工具】
画流程图工具 draw.io draw.io(现称为 diagrams.net)是一款在线图表绘制工具,可以用于创建各种类型的图表,如流程图、网络图、组织结构图、UML图、思维导图等。以下是关于它的一些优点、应用场景及使用方法: 优点&a…...

Revit二次开发选择过滤器,SelectionFilter
过滤器分为选择过滤器与规则过滤器 规则过滤器可以看我之前写的这一篇文章: Revit二次开发在项目中给链接模型附加过滤器 选择过滤器顾名思义就是可以将选择的构件ID集合传入并加入到视图过滤器中,有一些场景需要对某些构件进行过滤选择,但是没有共同的逻辑规则进行筛选的情况…...

【Linux】进程概念—环境变量
目录 一、冯诺依曼体系结构 二、操作系统(Operator System) 1 .概念 2 .设计OS的目的 3 . 定位 4 . 系统调用和库函数概念 三、进程 1 .基本概念 2 .描述进程-PCB(process control block)进程控制块 3 . 组织进程 4 . 查看进程 5 .通过系统调用获取进程…...
第十二章 Spring MVC 框架扩展和SSM框架整合(2023版本IDEA)
学习目标 12.1 Spring MVC 框架处理JSON数据12.1.1 JSON数据的传递处理12.1.2 JSON数据传递过程中的中文乱码和日期问题12.1.3 多视图解析器 12.2 Spring MVC 框架中的数据格式转换12.2.1 Spring MVC 框架数据转换流程12.2.2 编写自定义转换器12.2.3 使用InitBinder装配自定义编…...
js中的全局函数有这些
js中的全局函数有这些,记忆规则 6个编译 escape、unescape、decodeURI、decodeURIComponent、encodeURI、encodeURIComponent 2个数据处理 Number()、String() 4个数字处理 isFinite、isNaN、parseFloat、parseInt 1个特殊情况 eval()...
Android SurfaceFlinger——重绘闪烁处理(四十六)
在帧数据准备完成后,下一步是调用 devOptRepaintFlash() 函数处理显示输出设备的可选重绘闪烁问题,这里我们就来看一下重绘闪屏问题的处理方案。 1.更新输出设备的色彩配置文件2.更新与合成相关的状态3.计划合成帧图层4.写入合成状态5.设置颜色矩阵6.开始帧7.准备帧数据以进行…...
罗马数字转整数 C++
罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。 字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000 例如&#x…...
Day20_2--介绍同步加载和异步加载
同步加载和异步加载是处理程序或数据的两种不同方式,它们在处理任务的方式、效率和用户体验上有显著差异。下面是对这两种加载机制的详细介绍。 1. 同步加载(Synchronous Loading) 定义: 同步加载是一种加载数据或资源的方式&am…...
sftp做成一个池子
前言:开发中的需求要去对方的 ftp 服务器下载文件,这里下载文件采用 ftp 方式,下载之后程序再去解析文件的内容,然后再存数据库。下载过来的文件默认是 zip 格式,需要解压 unzip 一下,然后里面有一个 csv 文…...
全网最全-Netty从入门到精通
XiaoYongCai/2024/8/6 一:Netty入门 1.Netty概述 A.Netty的定义 Netty是一个提供异步事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。在Java领域,Netty被认为是除了Java原生NIO之外的最佳网络…...

C#知识|文件与目录操作:对象的创建、保存、读取
哈喽,你好啊,我是雷工! 面向对象编程的特点就是一切皆对象,操作的也是对象,本节学习文件与目录操作中,对象的保存; 以下为学习笔记。 01 对象的特点 ①:对象运行在内存中ÿ…...

自定义 SwiftUI 中符号图像的外观
文章目录 前言大小颜色渲染模式单色分层调色板多色 可变值设计变体示例代码结论 前言 符号图像是来自 Apple的SF Symbols 库的矢量图标,设计用于在 Apple 平台上使用。这些可缩放的图像适应不同的大小和重量,确保在我们的应用程序中具有一致的高质量图标…...
质量体系的重要
质量体系是为确保产品、服务或过程质量满足规定要求,由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面: 🏛️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限,形成层级清晰的管理网络…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...
在 Spring Boot 项目里,MYSQL中json类型字段使用
前言: 因为程序特殊需求导致,需要mysql数据库存储json类型数据,因此记录一下使用流程 1.java实体中新增字段 private List<User> users 2.增加mybatis-plus注解 TableField(typeHandler FastjsonTypeHandler.class) private Lis…...

nnUNet V2修改网络——暴力替换网络为UNet++
更换前,要用nnUNet V2跑通所用数据集,证明nnUNet V2、数据集、运行环境等没有问题 阅读nnU-Net V2 的 U-Net结构,初步了解要修改的网络,知己知彼,修改起来才能游刃有余。 U-Net存在两个局限,一是网络的最佳深度因应用场景而异,这取决于任务的难度和可用于训练的标注数…...

springboot 日志类切面,接口成功记录日志,失败不记录
springboot 日志类切面,接口成功记录日志,失败不记录 自定义一个注解方法 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/***…...
Spring Boot + MyBatis 集成支付宝支付流程
Spring Boot MyBatis 集成支付宝支付流程 核心流程 商户系统生成订单调用支付宝创建预支付订单用户跳转支付宝完成支付支付宝异步通知支付结果商户处理支付结果更新订单状态支付宝同步跳转回商户页面 代码实现示例(电脑网站支付) 1. 添加依赖 <!…...

Qt的学习(一)
1.什么是Qt Qt特指用来进行桌面应用开发(电脑上写的程序)涉及到的一套技术Qt无法开发网页前端,也不能开发移动应用。 客户端开发的重要任务:编写和用户交互的界面。一般来说和用户交互的界面,有两种典型风格&…...

结构化文件管理实战:实现目录自动创建与归类
手动操作容易因疲劳或疏忽导致命名错误、路径混乱等问题,进而引发后续程序异常。使用工具进行标准化操作,能有效降低出错概率。 需要快速整理大量文件的技术用户而言,这款工具提供了一种轻便高效的解决方案。程序体积仅有 156KB,…...

Qt的学习(二)
1. 创建Hello Word 两种方式,实现helloworld: 1.通过图形化的方式,在界面上创建出一个控件,显示helloworld 2.通过纯代码的方式,通过编写代码,在界面上创建控件, 显示hello world; …...