it_lv 2 weeks ago
parent
commit
d89657799d
3 changed files with 187 additions and 54 deletions
  1. 85 5
      第5阶段-搜索模块.md
  2. 9 5
      第6阶段-专辑详情.md
  3. 93 44
      简历汇总参考技术描述.md

+ 85 - 5
第5阶段-搜索模块.md

@@ -6,7 +6,27 @@
 
     ![tingshu055](assets/tingshu055-1698133726959-4.png)
 
-## 关系映射
+## 关系映射(如何设计索引库)
+
+一、设计索引库三个维度
+
+- 业务字段
+- 排序字段+过滤条件字段
+- 辅助字段
+
+二、其中索引库中特殊字段(字段映射)
+
+- Text类型应用-需要全文检索
+  - 专辑标题/简介 需要采用**ik_max_work**分词产生倒排索引
+- Keyword类型应用-精确查询
+  - 主播名称,付费类型
+- Nested类型应用
+  - 专辑标签(标签ID,标签值ID)列表
+
+三、创建索引库
+
+- 方式一:在Kibana中采用restfulAPI 创建索引同时设置映射
+- 方式二:SpringDataElasticSearch创建实体类完成索引库映射、提供持久层Repository启动项目扫描完成创建
 
 映射需要做实际页面需要展示的内容,比如标题 简介需要被搜索,需要做分词
 
@@ -34,6 +54,18 @@
 
 根据用户点赞、评论、收藏、播放数据综合排序取出前10名
 
+> 采用分布式定时任务xxl-job每隔6小时更新Redis中hash结构推荐榜数据
+>
+> 1. 执行器新建任务
+>    1. 获取所有1级分类ID
+>    2. 获取所有排序方式字段
+>    3. 为每个1级分类,遍历所有排序字段得到所有排序字段TOP20
+>    4. 写入Redis中hash结构:将1级分类ID作为Key,将排序字段作为field,将TOP20专辑列表作为Value
+> 2. 在调度中心配置任务
+>    1. 新增执行器
+>    2. 新增任务配置任务触发时间,启动任务
+> 3. 只要专辑索引库中统计数值随着用户各种访问行为进行增量变动
+
 ### 分词器配置
 
 #### IK分词器配置
@@ -78,7 +110,7 @@ GET _analyze
 
 ik分词器如何自定义分词
 
-进入路径:/mydata/elasticsearch/plugins/elasticsearch-analysis-ik-7.8.0/config
+进入路径:/mydata/elasticsearch/plugins/ik/config
 
 ~~~shell
 # 执行分词
@@ -156,10 +188,54 @@ POST /_analyze
 
 ### 首页搜索
 
+在小程序门户首页搜索框用户录入任意关键字进行全文检索、根据首页任意级分类进行过滤、根据标签条件进行过滤。查询结果分页展示,如果有关键字检索将结果中存在关键字进行高亮显示。
+
+开发步骤
+
+第一步:根据需求在Kibana中编写DSL查询语句
+
+> 根据业务需求确定查询请求请求体参数
+>
+> 如果存在条件查询需要:query属性
+>
+> - 1大条件:关键字检索
+> - 2大条件:分类过滤
+> - 3大条件:标签过滤
+>
+> 如果需要进行分页需要:from,size属性  **注意:业务规定不需要深度分页(<=10000)**
+>
+> 如果需要高亮需求:highlight **注意:存在关键字全文检索** 高亮字段及高亮html标签
+>
+> 如果需要对结果进行排序:sort 确定排序字段跟排序方式即可
+>
+> 减少查询响应结果需要指定检索返回字段:**_source 提高检索接口响应效率:按需检索返回字段**
+
+第二步:通过Java客户端拼接完整DSL语句,解析ES响应结果
+
+> 解决参考ES官方文档,整体采用ES原始客户端传统写法,局部采用ES8.0后提供全新Lambda写法
+>
+> 1. 准备检索请求对象(包含完整DSL)
+> 2. 执行检索(调用ES检索接口)
+> 3. 解析ES响应结果
+
 ### 自动补全
 
 前端根据输入内容调用后端自动补全接口
 
+业务需求:只要专辑被上架到索引库,将专辑标题、主播名称存入提词索引库 采用ES提供SuggestAPI完成关键字自动补全。提词索引库中凡是需要被自动补全字段Completion类型。提升用户体验。
+
+第一步:根据需求在Kibana中编写DSL查询语句
+
+> 设置请求体参数:suggest 分别检索,中文提词字段、拼音提词字段、拼音首字母提词字段
+>
+> 解析ES响应结果
+
+第二步:通过Java客户端拼接完整DSL语句,解析ES响应结果
+
+> 略
+>
+> 解析结果:解析提词响应结果,如果提词命中数量小于10.尝试采用全文检索检索专辑索引库中专辑标题,补全到10个返回
+
 ### 专辑下架
 
 根据专辑的ID删除ES索引,删除Redis缓存,需要考虑布隆过滤器问题
@@ -168,7 +244,9 @@ POST /_analyze
 
 放入到布隆过滤器中。
 
-### 热度数据统计
+### 热度数据统计(更新统计)
+
+稀释写操作方案
 
 ~~~java
 @Override
@@ -182,7 +260,7 @@ public void incrHotScore(Long albumID) {
     Double count = this.redisTemplate.opsForZSet().incrementScore(key, "albumID:" + albumID, 1);
     
     //  判断
-    if (count%1000==0){ //访问一千次更新一次索引
+    if (count%1000==0){ //访问一千次更新一次索引或MySQL
         //根据专辑id查询对应专辑索引数据
         //修改热度值
         //更新索引数据
@@ -237,7 +315,7 @@ eg: 原文 nice to meet you     英文按空格分词: nice| to| meet| you
 
 产生分词后便会形成正向索引  即: 从左侧的原文到右侧的分词
 
-![image-20240320203123747](assets/image-20240320203123747.png)
+ ![image-20240320203123747](assets/image-20240320203123747.png)
 
 倒排索引: 是反向将分词与文本的对应  eg: "中华"这个分词对应原文档中的1号文本
 
@@ -255,6 +333,8 @@ eg 当用户搜索"清朝华人买办",包含多个分词,全文检索引擎要
 
 #### ES深度分页问题
 
+**业务限制**:不支持深度分页 对于全文检索而言1W条记录以后数据,跟用户搜索内容没有相关性
+
 ````shell
 // 我们项目中使用from+size实现分页
 // 表示跳过5000个文档,返回接下来的10个文档

+ 9 - 5
第6阶段-专辑详情.md

@@ -67,7 +67,7 @@
 
 #### 缓存雪崩
 
-**大量key同时失效**
+**大量key同时失效或Redis单机故障**
 
 我们设置缓存时采用了**相同的过期时**间,导致缓存在**某一时刻同时失效**,请求全部**转发到DB**,DB瞬时压力过重雪崩。
 
@@ -104,13 +104,13 @@
 
 #### 数据一致性
 
-双删模式:两次删除redis
+延迟双删方案:两次删除缓存期间延迟一段时间
 
-异步双删:通过MQ获取消息进行删除
+分布式读写锁方案:禁止并发读写,写写,写读
+
+MySQLBinlog日志方案:
 
-延迟双删:MQ获取消息之后,延迟一段时间再删
 
-定时双删:定时任务
 
 <img src="assets/image-20240118212550116.png" alt="image-20240118212550116" style="zoom:67%;" />
 
@@ -130,6 +130,10 @@ MySQL主从复制原理
 
 Master 主库在事务提交时,会把数据变更记录在二进制日志文件 Binlog 中。
 
+- ROW 记录行数据 缺点:效率低
+- Statement 记录增删改命令 缺点:执行SQL包含时间函数导致主从数据不一致
+- MIXED混合模式
+
 从库读取主库的二进制日志文件 Binlog ,写入到从库的中继日志 Relay Log 。
 
 slave重做中继日志中的事件,将改变反映它自己的数据。

+ 93 - 44
简历汇总参考技术描述.md

@@ -215,7 +215,7 @@
   - 认证切面类中:拿着要求前端提交设备标识+IP所属行政区域,如果发现设备变更,或者异地登录将Token删除,响应208业务状态码,前端引导用户再次登录。
   - 将Token过期时间设置适当短(Token过期后问题不符存在)
 
-#### 3. 采用ElasticSearch进行站内多条件专辑检索、首页置顶分类热门专辑、关键字自动补全、竞价排名等功能.
+#### 3. 采用ElasticSearch实现站内多条件专辑检索、首页置顶分类热门专辑、关键字自动补全、竞价排名等功能
 
 背景:
 
@@ -232,20 +232,20 @@
       - 三、排序字段-进行排序
       - 四、辅助字段
 
-    - 2.专辑索引数据同步-利用Kakfa消息队列
+    - 2.专辑索引数据同步-利用RabbitMQ消息队列
 
-      - 专辑服务中经过内容安全审核,发送消息到上架话题(存放专辑ID)
-      - 搜索服务监听话题中消息,根据消息中专辑ID采用异步任务**CompletableFuture**+**线程池** 封装索引库文档对象,将专辑文档存入ES索引库
-        - 开启并行线程分别OpenFeign调用专辑服务查询专辑信息(包含标签列表)、查询专辑统计信息
+      - 专辑服务中经过内容安全审核,发送消息到专辑交换机-路由到上架队列(存放专辑ID)
+      - 搜索服务监听上架队列中消息,根据消息中专辑ID采用异步任务**CompletableFuture**+**线程池** 封装索引库文档对象,将专辑文档存入ES索引库
+        - 开启并行线程分别发起OpenFeign调用专辑服务查询专辑信息(包含标签列表)、查询专辑统计信息
         - 专辑信息异步任务执行完毕后,开启两个子线程查询专辑分类及专辑主播信息
-      - 将上架专辑ID存入分布式布隆过滤器(解决缓存穿透)
-      - 将上架专辑 名称 存入提词索引库(用于自动联想/补全功能)
+      - 将上架专辑ID存入分布式布隆过滤器(解决缓存穿透问题
+      - 将上架专辑/主播名称 存入提词索引库(用于自动联想/补全功能)
 
     - 2.站内搜索
 
       > 封装检索DSL语句:
       >
-      > 4.设置查询条件 条件1:关键字 条件2:分类ID 条件3:标签 三个大条件采用and
+      > 设置查询条件 条件1:关键字 条件2:分类ID 条件3:标签 三个大条件  采用and
       > 4.1 模拟用户录入“古典”关键字进行查询  需求匹配查询专辑标题或简介,或精确查询主播名称。关键字查询大条件包含三个子条件,三个子条件满足其一即可。考虑到用户录入内容千奇百怪,故选择**must**合适,会有相关性算分。
       >
       > 4.2 模拟用户选择“有声书=2”1级 分类进行过滤数据,分类数据是系统限制用户选择,适合于进行缓存,相同分类数据进行缓存,缓存命中率比较高。故采用**filter**
@@ -262,7 +262,7 @@
 
 - 置顶分类热门专辑
 
-  - 业务:在门户前端/app/小程序首页展示每个1级分类下置顶三级分类,同时还需要展示置顶分类下包含热门专辑,为了页面排版,前端展示7个置顶分类+全部、某个置顶分类下展示6个热度较高专辑。点击首页专辑,也支持根据任意级分类进行检索
+  - 业务:在门户前端/app/小程序首页展示每个1级分类下置顶三级分类,同时还需要展示置顶分类下包含热门专辑,为了页面排版,前端展示7个置顶分类+全部、某个置顶分类下展示6个热度较高专辑。点击首页分类,也支持根据任意级分类进行检索
 
   - 实现
 
@@ -336,7 +336,7 @@
 
 解决方案:
 
-应对高并发场景:**1.缓存**  **2.线程池+异步**   **3.限流**   **4.SQL优化** **5.搭建集群**
+服务器端应对高并发手段:**1.缓存**  **2.线程池+异步**   **3.限流**   **4.SQL优化** **5.搭建集群**
 
 创建线程方式:
 
@@ -353,7 +353,7 @@
 
   - 统一管理JVM用户线程,提供监控功能
 
-    > 工具类Executors创建线程池(线程数或阻塞队列长度Integer最大值,容易出现栈溢出,堆内存移除)、自定义JDK线程池**ThreadPoolExecutor**,项目集成Zipkin链路追踪组件,发现问题:当多个远程调用串行调用,链路追踪完整(OpenFeign远程调用会自动将链路ID传递下游服务),改为多线程异步后,远程调用由开启子线程调用,子线程无法自动获取主线程中链路ID,导致链路不完整。解决办法:**采用Spring线程池类ThreadPoolTaskExecutor**,包含JDK线程池所有功能,提供装饰器setTaskDecorator编写主线程跟子线程之间传递参数(链路ID)解决问题。
+    > 工具类Executors创建线程池(线程数或阻塞队列长度Integer最大值,容易出现栈溢出,堆内存移除)、自定义JDK线程池**ThreadPoolExecutor**,项目**集成Zipkin链路追踪**组件,发现**问题**:当多个远程调用串行调用,链路追踪完整(OpenFeign远程调用会自动将链路ID传递下游服务),改为多线程异步后,远程调用由开启子线程调用,子线程无法自动获取主线程中链路ID,导致链路不完整。解决办法:**采用Spring线程池类ThreadPoolTaskExecutor**,包含JDK线程池所有功能,提供装饰器setTaskDecorator编写主线程跟子线程之间传递参数(链路ID)解决问题。
     >
     > 准备好:线程池作用原理、线程池7个参数、线程池拒绝策略、线程池核心数如何设置:2N(核心数)+1阻塞队列一般设置为300~500左右
     >
@@ -372,21 +372,32 @@
     - 组合异步任务:CompletableFuture.allOf(CompletableFuture<?>... cfs).join()所有任务执行完毕
     - 只需要某个任务执行结束 .CompletableFuture.anyOf(CompletableFuture<?>... cfs) 
 
-  - QPS计算方式
+  - QPS平均耗时优差衡量
 
+    - 传统项目接口耗时小于1s就OK
+    - 互联网项目
+      - 一级接口:一级页面,如:首页或商品详情页
+      - 20并发小于150ms,通过率  >=99.9%
+      - 二级接口:二级页面,如:课程列表、订单列表
+      - 2、二级接口10并发小于200ms,通过率 >=99.9%
+      - 三级接口:三级页面,如:订单详情页、课程详情页
+        - 三级接口5并大小于300ms,通过率 >=99.9%
+  
+  - QPS计算方式
+  
     > 通常情况下平均接口响应时间小于200ms,普通接口小于500ms,特殊接口要求小于1s
     >
     > ![image-20240604163917920](assets/image-20240604163917920.png)
-
+  
   - 优化结果:压测工具(ApacheJmeter,ab,ApiPost/ApiFox-在线接口文档及压测一体工具)
-
+  
     > 开发环境:压测并发100持续1分钟 专辑信息接口-SQL优化(至少达到Range级别)-80ms左右
     >
-    > ​                     压测并发100持续1分钟 专辑信息接口-SQL优化(至少达到Range级别)-50ms左右
+    > ​                     压测并发100持续1分钟 专辑信息接口-SQL优化+缓存(至少达到Range级别)-50ms左右
     >
-    > 总计请求数:2w+
+    > 总计请求数:2w+	
     >
-    > 成功比例:99.98% 不能大于百分之1
+    > 成功比例:99.98% 不能大于百分之0.01
     >
     > 平均接口响应时间:400ms--->260ms
 
@@ -453,11 +464,11 @@
 
     - 加锁 通过lua脚本操作hash结构的"锁"
 
-      > 1. 判断锁是非被占用 0 说明锁空闲 or 判断持有锁的线程是否为当前线程 
+      > 1. 判断锁是否存在0 说明锁空闲 or 判断持有锁的线程是否为当前线程 
       >
       > 2. 满足第1步加锁条件,当前线程可以加锁
       >
-      >    2.1 对Hash中重入次数+1
+      >    2.1 对Hash中Value重入次数+1
       >
       >    2.2 将hash锁过期时间设置为30s
       >    
@@ -468,20 +479,22 @@
     - 续期 通过lua脚本操作hash结构的"锁"
 
       > 持有锁的线程开启锁续期,开启看门狗续期的条件:**锁释放时间**必须等于**-1**,持有锁的线程加锁成功,开启固定延迟时间为10s续期任务,每次续期锁为30s
-  >
-      > 1. 判断持有锁的线程是否为当前线程 条件成立:说明线程没有主动调用unlock释放锁(业务还未执行结束)
-      > 2. 再次对锁的过期时间设置为30s
-      > 3. 返回1续期成功
-      > 4. 反之:当前线程的锁被线程释放掉,锁过期.返回0
-    - 解锁 通过lua脚本操作hash结构的"锁"
-  
-      > 1. 判断持有锁的线程是否为当前线程
-  >    1. 当前线程已经不再持有锁,锁自动过期 返回null
-      > 2. 当前线程是持有锁的线程,对重入次数进行-1 返回重入次数
-      >    1. 重入次数-1后重入次数大于0,再次对锁的过期时间设置为30s 确保上一次加锁任务逻辑有时间执行,返回false
-      >    2. 重入次数-1后,重入次数小于等于0
-      >       1.  删除锁
-      >       2. 利用Redis发布订阅 命令publish通知阻塞的客户端可以抢锁了
+
+>
+    > 1. 判断持有锁的线程是否为当前线程 条件成立:说明线程没有主动调用unlock释放锁(业务还未执行结束)
+    > 2. 再次对锁的过期时间设置为30s
+    > 3. 返回1续期成功
+    > 4. 反之:当前线程的锁被线程释放掉,锁过期.返回0
+
+解锁 通过lua脚本操作hash结构的"锁"
+
+    > 1. 判断持有锁的线程是否为当前线程
+>    1. 当前线程已经不再持有锁,锁自动过期 返回null
+    > 2. 当前线程是持有锁的线程,对重入次数进行-1 返回重入次数
+    >    1. 重入次数-1后重入次数大于0,再次对锁的过期时间设置为30s 确保上一次加锁任务逻辑有时间执行,返回false
+    >    2. 重入次数-1后,重入次数小于等于0
+    >       1.  删除锁
+    >       2. 利用Redis发布订阅模式publish命令通知阻塞的客户端可以抢锁了
 
 #### 6. 采用自定义缓存注解优化去除冗余缓存及分布式锁业务代码、提高代码复用性
 
@@ -519,7 +532,9 @@
   >
   >    2.2 基于RedissonClient对象创建锁对象 入参为锁key,在Redis中锁结构hash中作为锁名称
   >
-  >    2.3 调用锁对象lock方法或者tryLock方法。没有看门狗机制:多进程同时执行业务,违背排他性
+  >    2.3 调用锁对象lock方法或者tryLock方法。如果没有看门狗机制:多进程同时执行业务,违背排他性
+  >
+  >    开启看门狗条件:lock,tryLock方法入参为空,默认框架底层锁释放时间为
   >
   >    ​       lock方法会一直阻塞到获取锁成功
   >
@@ -730,21 +745,50 @@
 
 除了展示“商品”信息外,还需要在订单确认页面中采用隐藏域方式,流水号、跟本次订单签名信息
 
+策略+工厂模式:处理不同商品类别结算逻辑;不同虚拟物品发货
+
 流水号:订单确认页渲染接口服务端,采用UUID生成本次订单流水号字符串,将流水号存入Redis设置ttl-5分钟。
 
 签   名:订单确认页面中将所有订单VO参数参与加密 对称加密算法(排序好订单vo所有值+"秘钥") 得到对应签名值
 
 - 步骤二:订单提交(余额支付)
 
-  > 业务流程:“商品”三种:1.VIP会员 2.专辑 3.声音,其中VIP会员及专辑支持两种付款方式(余额跟微信),声音仅支持余额付款。当选择余额支付,首先**业务校验**(一、验证流水号**采用lua脚本(判断跟删除原子性)**验证流水号及删除流水号。二、验签,采用订单确认页相同对称加密算法对订单VO信息+秘钥再次进行签名比对两次签名值是否一致);经过业务校验后,`核心业务1`:保存订单,保存订单其中订单编号(确保全局唯一:采用年月日+雪花算法);保存订单商品明细列表;保存优惠明细列表,此时订单状态:**未支付。**`核心业务2`:扣减账户余额且增加账户变动日志,只要余额扣减成功将地订单状态修改为:**已支付**。`核心业务3`:虚拟物品发货,专辑/声音新增购买记录即可(订单详情页面中声音付费标识-查询用户购买情况);VIP会员新增会员购买记录,更新用户VIP标识及延长会员过期时间。
-  >
-  > **亮点**:考虑到代码可扩展性,后续可能会再增加其他商品类型代码编写大量if else if,采用**策略+工厂设计模式**(**展开**)符合编程“**开闭原则**”,如果增加新增项目类型,不需要修改现有代码,再次新增对应购买项目策略实现类即可。
-  >
-  > **亮点**:在三项核心业务对应三个服务三个数据库面临分布式事务问题,**采用阿里巴巴/Apache Seata框架**提供AT模式解决(**展开**工作原理+写隔离/全局锁机制)分布式事务问题;当时遇到问题:由于项目采用全局异常处理机制,导致(Feign远程调用)即使分之事务发生异常,被全局异常类拦截完成处理,导致Feign请求没有异常,导致**分布式事务失效**。解决方案:1.事务发起方判断Feign响应业务状态码(成功业务状态码Integer是200,使用==判断判断返回false,原因:Integer将-128~127将常用数值对应Integer对象进行缓存,改为equals判断),手动抛出异常,被事务发起方感知异常 2. 分之事务业务逻辑中例如:扣减账户结果失败,手动调用Seata全局事务回滚方法,参考:https://seata.apache.org/zh-cn/blog/seata-spring-boot-aop-aspectj
+> 业务流程:“商品”三种:1.VIP会员 2.专辑 3.声音,其中VIP会员及专辑支持两种付款方式(余额跟微信),声音仅支持余额付款。当选择余额支付,首先**业务校验**(一、验证流水号**采用lua脚本(判断跟删除原子性)**验证流水号及删除流水号。二、验签,采用订单确认页相同对称加密算法对订单VO信息+秘钥再次进行签名比对两次签名值是否一致);经过业务校验后,`核心业务1`:保存订单,保存订单其中订单编号(确保全局唯一:采用年月日+雪花算法);保存订单商品明细列表;保存优惠明细列表,此时订单状态:**未支付。**`核心业务2`:扣减账户余额且增加账户变动日志,只要余额扣减成功将地订单状态修改为:**已支付**。`核心业务3`:虚拟物品发货,专辑/声音新增购买记录即可(订单详情页面中声音付费标识-查询用户购买情况);VIP会员新增会员购买记录,更新用户VIP标识及延长会员过期时间。
+>
+> **亮点**:考虑到代码可扩展性,后续可能会再增加其他商品类型代码编写大量if else if,采用**策略+工厂设计模式**(**展开**)符合编程“**开闭原则**”,如果增加新增项目类型,不需要修改现有代码,再次新增对应购买项目策略实现类即可。
+>
+> **亮点**:在三项核心业务对应三个服务三个数据库面临分布式事务问题,**采用阿里巴巴/Apache Seata框架**提供AT模式解决(**展开**工作原理+写隔离/全局锁机制)分布式事务问题;当时遇到问题:由于项目采用全局异常处理机制,导致(Feign远程调用)即使分之事务发生异常,被全局异常类拦截完成处理,导致Feign请求没有异常,导致**分布式事务失效**。解决方案:1.事务发起方判断Feign响应业务状态码(成功业务状态码Integer是200,使用==判断判断返回false,原因:Integer将-128~127将常用数值对应Integer对象进行缓存,改为equals判断),手动抛出异常,被事务发起方感知异常 2. 分之事务业务逻辑中例如:扣减账户结果失败,手动调用Seata全局事务回滚方法,参考:https://seata.apache.org/zh-cn/blog/seata-spring-boot-aop-aspectj
+>
+> 分布式事务解决方案Seata-AT模式工作原理:
+>
+> 一阶段:
+>
+> 1. 事务发起方开启全局事务,Seata生成本次全局事务ID,全局事务ID会在OpenFeign远程调用通过请求头传递到下游服务,全局事务内包含多个分之事务,就能做到同生共死
+> 2. 某个分之事务RM,通过Seata生成分之事务跟全局事务绑定
+> 3. 开启本地事务包含业务数据+回滚日志记录,必须获取到业务记录ID对应全局锁,此时会立即提交本地事务
+> 4. 上报RM事务状态到TC(Seata服务端)
+>
+> 二阶段:
+>
+> TC会根据所有RM在1阶段提交事务状态决定二阶段提交或回滚。
+>
+> RM:收到 TC 的分支提交请求,把请求放入一个异步任务的队列中,马上返回提交成功的结果给 TC,异步和批量地删除相应 UNDO LOG 记录
+>
+> RM:收到 TC 的分支回滚请求,开启一个本地事务内根据xId+branchId相应的 UNDO LOG 记录,得到更新前记录完成数据回滚。
+>
+> **AT优点:无代码入侵(Seata底层基于undo日志表实现补偿)、一阶段提交本地事务,性能较好**
+>
+> **AT缺点:最终一致性解决方案、全局锁+日志多少影响性能**
+>
+> **全局锁机制:**加分项
+>
+> - 一阶段本地事务提交前,需要确保先拿到 **全局锁** 
+> - 拿不到 **全局锁** ,不能提交本地事务。
+> - 拿 **全局锁** 的尝试被限制在一定范围内(300ms重试30次),超出范围将放弃,并回滚本地事务,释放本地锁
 
 如果用户选择第三方支付平台:微信涉及调用微信支付SDK,用户付款动作。基于延迟任务,完成延迟关单:将超时未支付订单自动关闭;
 
-#### 10. 利用流水号机制避免小程序回退造成的订单重复提交-采用Lua脚本确保判断删除原子性
+#### 10. 利用流水号机制避免回退造成的订单重复提交-采用Lua脚本确保判断删除原子性
 
 - 订单结算页-生成流水号
 
@@ -780,18 +824,23 @@
   > 4. 采用加签相同方式进行再次签名:md5(明文参数, **秘钥**) 得到新签名
   > 5. 判断两次签名值是否一致 一致:继续后续业务 不一致:参数被篡改,业务终止
 
-对称加密:效率高,安全系数低
 
-非对称加密:效率低,安全性系数高
 
-面试延伸:场景涉及要求安全系数很高Restful接口调用,如何防止该接口参数在网络传输中被篡改?
+对称加密:加密解密采用相同秘钥值例如:md5、HS256。效率高,安全系数低
+
+非对称加密:加密跟解密使用公私钥例如:RSA。效率低,安全性系数高
+
+
+
+面试延伸:场景涉及要求安全系数很高Restful接口调用,如何防止该接口请求体业务参数在网络传输中被篡改?
 
 答:采用非对称加密(RSA加密方式),产生两把“钥匙”:
 
 - 公钥:用来加密信息,A给B发送消息,拿着公钥进行加密。必须用配套私钥进行解密
-
 - 私钥:用来解密信息,收到来自A的消息,拿着私钥进行解密
 
+
+
 #### 12. 采用策略模式+工厂模式优化不同类型商品处理虚拟物品发货业务
 
 背景:目前项目中提供三种商品类别(产品经理规划后续可能还会进一步丰富会员体系,增加其他商品类别-视频)如果仍然采用传统if else if判断处理不同商品类别,代码可维护性很差,扩展性很差。 特点:不同类型商品“发货”逻辑各不一样,采用行为型设计模式:策略模式 为了能具备“开闭原则”采用工厂统一管理所有策略,提供策略标识返回策略实现类。