plantuml,es同步方案
This commit is contained in:
parent
7a990a9727
commit
207656f97d
|
@ -10,6 +10,7 @@
|
|||
"dependencies": {
|
||||
"hexo": "^6.3.0",
|
||||
"hexo-bridge": "^1.2.0",
|
||||
"hexo-filter-plantuml": "^2.1.1",
|
||||
"hexo-generator-archive": "^2.0.0",
|
||||
"hexo-generator-category": "^2.0.0",
|
||||
"hexo-generator-feed": "^3.0.0",
|
||||
|
@ -971,6 +972,11 @@
|
|||
"node": ">=10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/hexo-filter-plantuml": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmmirror.com/hexo-filter-plantuml/-/hexo-filter-plantuml-2.1.1.tgz",
|
||||
"integrity": "sha512-MUBbuDyPiq1cN1rJffe9izZqWAHpAGVW25CGe4WHqjD4IkdcNjhrk9l7WTej9IGQCO132UJeTkOqreHanKdQag=="
|
||||
},
|
||||
"node_modules/hexo-front-matter": {
|
||||
"version": "3.0.0",
|
||||
"license": "MIT",
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
"dependencies": {
|
||||
"hexo": "^6.3.0",
|
||||
"hexo-bridge": "^1.2.0",
|
||||
"hexo-filter-plantuml": "^2.1.1",
|
||||
"hexo-generator-archive": "^2.0.0",
|
||||
"hexo-generator-category": "^2.0.0",
|
||||
"hexo-generator-feed": "^3.0.0",
|
||||
|
|
|
@ -0,0 +1,154 @@
|
|||
title: 记一次业务系统与ES的同步方案升级
|
||||
tags: []
|
||||
categories: []
|
||||
date: 2023-08-28 15:05:47
|
||||
---
|
||||
# 背景
|
||||
|
||||
目前ES中接入了诸多业务线,其技术方案一直延续第一版,由ES处理获取数据和搜索的业务逻辑。随着时间的发展,在**并发场景下发现了数据不一致,数据被重复覆盖的问题**。而且从架构上,search引入业务系统的API也不是合理的架构。
|
||||
|
||||
# 现状
|
||||
|
||||
**写入链路如下**
|
||||
|
||||
```plantuml
|
||||
@startuml
|
||||
业务系统 -> MQ: 发送变更事件
|
||||
MQ --> Search: 订阅变更事件
|
||||
|
||||
Search -> 业务系统: 获取业务数据
|
||||
Search -> Search: 幂等处理
|
||||
Search -> ES: 索引数据
|
||||
@enduml
|
||||
```
|
||||
|
||||
**读取链路如下**
|
||||
|
||||
```plantuml
|
||||
@startuml
|
||||
用户 -> 业务系统: 发起搜索
|
||||
业务系统 -> Search: 发起检索请求
|
||||
Search --> Search: 组装请求
|
||||
Search -> ES: 检索数据
|
||||
ES --> Search: 响应数据
|
||||
Search --> 业务系统: 返回响应
|
||||
业务系统 -> 业务系统: 读取详细业务数据
|
||||
业务系统 --> 用户: 展示搜索结果
|
||||
@enduml
|
||||
```
|
||||
|
||||
因为MQ的发送后的消费并不能保证强一致,可能会导致乱序执行。至于不用分片顺序,因为MQ中会有批量,导致无法区分分片信息。search同时还需要作幂等,限流等,导致Search服务更重。
|
||||
|
||||
# 目标
|
||||
|
||||
暂时的目标如下:
|
||||
|
||||
1. 减轻Search的循环依赖的问题,Search不再依赖业务系统。
|
||||
2. 减轻Search服务的业务逻辑
|
||||
3. 解决并发下的数据不一致问题
|
||||
|
||||
# 技术方案
|
||||
|
||||
本次改造只涉及写入流程,不会涉及读取流程
|
||||
|
||||
## 主要优化
|
||||
|
||||
* 全流程新单链路独立,优化新单的可搜索延迟
|
||||
* Search去除业务系统依赖,由业务系统自发自接数据,处理后统一发送到Search。
|
||||
|
||||
## 时序图
|
||||
|
||||
```plantuml
|
||||
@startuml
|
||||
|
||||
|
||||
participant 业务系统 as 业务系统
|
||||
queue 变更MQ as 变更MQ
|
||||
queue 分片顺序新单MQ as 分片顺序新单MQ
|
||||
queue 分片顺序MQ as 分片顺序MQ
|
||||
participant Search as Search
|
||||
participant ES as ES
|
||||
|
||||
业务系统 -> 变更MQ: 发送变更事件
|
||||
变更MQ --> 业务系统: 订阅变更事件
|
||||
alt 并发控制
|
||||
业务系统 -> 业务系统: 获取业务数据
|
||||
alt 是新单
|
||||
业务系统 -> 分片顺序新单MQ: 发送业务数据
|
||||
分片顺序新单MQ -> Search: 订阅业务数据
|
||||
Search -> ES: 索引数据
|
||||
else 不是新单
|
||||
业务系统 -> 分片顺序MQ: 发送业务数据
|
||||
分片顺序MQ -> Search: 订阅业务数据
|
||||
Search -> ES: 索引数据
|
||||
end
|
||||
end
|
||||
@enduml
|
||||
```
|
||||
|
||||
## 新单的延迟优化
|
||||
|
||||
在一般业务场景中,新单的延迟比单子的搜索不准确感知更明显。针对新单的我们需要做一些特殊优化,使延迟降低到无感的地步。
|
||||
|
||||
**建议**
|
||||
|
||||
新建单操作与更新操作隔离,新建单使用单独的topic
|
||||
|
||||
## 并发下数据一致性
|
||||
|
||||
在无法保证单次操作时,仅发送一次变更事件的情况下,使用分布式锁保证数据一致性,是相对来说比较好的方案。
|
||||
|
||||
**建议**
|
||||
|
||||
使用分布式锁,对订单上锁,加锁范围 见 时序图的【并发控制】
|
||||
|
||||
**缓解ES的写入压力**
|
||||
|
||||
很多时候,更新可能只是触发一次保存操作,实际上数据没有变化的,业务系统中可以做一层对比层,数据有变化再发送到Search。由此缓解ES的写入压力。其次与单次操作无法保证仅发送一次变更事件一样,多次变更是无效的。
|
||||
|
||||
**建议**
|
||||
|
||||
内部使用DB或者Redis,建立一层针对单号的对比逻辑,与上次发送的数据如果一致,则不发送。
|
||||
|
||||
该对比逻辑需要有开关控制,使用快捷的手段【acm,db配置等】一分钟内可操作开启关闭
|
||||
|
||||
## 数据传输优化
|
||||
|
||||
在系统中以拖车40HC*30箱为例【WY268171】,履约系统的业务数据转换成JSON后有27万字符,270KB。这种场景下对MQ的压力会相对较大,对于大JSON是否需要空间换时间,值得考虑。
|
||||
|
||||
**从空间角度来说**
|
||||
|
||||
以该JSON为例,如使用gzip压缩,大小可以压缩到12KB,4%的压缩率,即压缩后节约96%的空间。但是代价是什么呢?
|
||||
|
||||
**从时间角度来说**
|
||||
|
||||
该字符串压缩100次 632毫秒,每次压缩6毫秒解压100次 361毫秒,每次解压3.6毫秒
|
||||
|
||||
**结论**
|
||||
|
||||
由此可见,对于大于1万个字符的字符串,以空间换时间,比较划算
|
||||
|
||||
压缩相关由Search提供工具包
|
||||
|
||||
1. 压缩工具类
|
||||
2. 压缩枚举
|
||||
3. Message的数据处理
|
||||
|
||||
# Message定义
|
||||
|
||||
|字段|类型|备注|
|
||||
| ------------| --------------------| ----------------------------|
|
||||
|indexName|String|索引类型,由Search提供常量|
|
||||
|indexId|String|索引下唯一的ID|
|
||||
|systemName|String|系统名称,系统随便定义|
|
||||
|timestamp|long|时间戳|
|
||||
|compress·|String|压缩类型,枚举【todo】|
|
||||
|dataJson|String|明文数据【未压缩下的数据】|
|
||||
|dataByte|byte[]|字节数组【压缩后的数据】|
|
||||
|paramExt|Map<String,String>|附属信息|
|
||||
|
||||
|
||||
# 结果
|
||||
|
||||
|
||||
// todo
|
Loading…
Reference in New Issue