475 lines
22 KiB
Markdown
475 lines
22 KiB
Markdown
# Architecture Research
|
||
|
||
**Domain:** IoT 卡管理 + 多级分销 + 分佣结算平台(Brownfield 单体)
|
||
**Researched:** 2026-03-27
|
||
**Confidence:** HIGH(基于当前代码库深度分析 + 该领域已知模式验证)
|
||
|
||
---
|
||
|
||
## 当前架构概述
|
||
|
||
### 系统总览
|
||
|
||
```
|
||
┌──────────────────────────────────────────────────────────────────────┐
|
||
│ API 进程(cmd/api) │
|
||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
||
│ │ /auth │ │ /admin │ │ /c/v1 │ │ /callback│ │
|
||
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
|
||
│ │ │ │ │ │
|
||
│ └─────────────┴──── Handler 层 ────────────┘ │
|
||
│ │ │
|
||
│ Service 层(~55 个服务包) │
|
||
│ │ │
|
||
│ Store 层(54 个 Store 文件) │
|
||
│ │ │
|
||
│ PostgreSQL + Redis │
|
||
└──────────────────────────────────────────────────────────────────────┘
|
||
|
||
┌──────────────────────────────────────────────────────────────────────┐
|
||
│ Worker 进程(cmd/worker) │
|
||
│ ┌────────────────┐ ┌──────────────────┐ ┌─────────────────────┐ │
|
||
│ │ Asynq Worker │ │ 轮询调度器 │ │ Asynq Scheduler │ │
|
||
│ │ (任务消费) │ │ (Redis SortedSet)│ │ (定时任务) │ │
|
||
│ └────────┬───────┘ └────────┬─────────┘ └──────────┬──────────┘ │
|
||
│ └──────────────────┴────────────────────────┘ │
|
||
│ │ │
|
||
│ Task Handler 层(16 个任务) │
|
||
│ │ │
|
||
│ Service / Store 层(复用 API 侧) │
|
||
└──────────────────────────────────────────────────────────────────────┘
|
||
|
||
外部集成:
|
||
Gateway(运营商接口) ← HTTP Client → IoT 卡/设备状态同步
|
||
微信支付(JSAPI/H5) ← PowerWeChat SDK
|
||
富友支付 ← 自研 SDK(pkg/fuiou)
|
||
联通云 OSS ← S3 兼容(批量导入/导出)
|
||
```
|
||
|
||
### 组件职责
|
||
|
||
| 组件 | 职责 | 关键文件 |
|
||
|------|------|---------|
|
||
| Bootstrap | 依赖装配,进程启动唯一入口 | `internal/bootstrap/*.go` |
|
||
| RouteSpec + Register() | 路由即文档,单次声明驱动 Fiber + OpenAPI | `internal/routes/registry.go` |
|
||
| Auth Middleware | JWT/Redis Token 解析,写入 UserContextInfo | `pkg/middleware/auth.go` |
|
||
| DataScope Filter | Store 层显式过滤,多租户数据隔离 | `pkg/middleware/data_scope.go` |
|
||
| Service(业务核心)| 幂等、事务编排、业务规则、任务提交 | `internal/service/**` |
|
||
| Store(数据访问)| SQL、分页、显式权限过滤 | `internal/store/postgres/*.go` |
|
||
| Task Handler | Asynq 任务处理(轮询/佣金/导入/过期) | `internal/task/*.go` |
|
||
| Polling Scheduler | Redis SortedSet 驱动卡片轮询队列 | `internal/polling/scheduler.go` |
|
||
| Commission Calculation | 多级分佣链计算(差价佣金 + 一次性佣金) | `internal/service/commission_calculation/` |
|
||
|
||
---
|
||
|
||
## 组件边界分析
|
||
|
||
### 当前已正确划分的边界
|
||
|
||
**① 双进程隔离(API vs Worker)**
|
||
- API 进程:HTTP 快速响应,无阻塞 I/O
|
||
- Worker 进程:轮询、批量导入、佣金计算、定时任务
|
||
- 边界清晰,独立部署、独立扩容 ✅
|
||
|
||
**② 数据权限隔离(Shop 层级过滤)**
|
||
- 用户身份 → UserContextInfo → SubordinateShopIDs(Redis 缓存)
|
||
- Store 层显式调用 ApplyShopFilter / ApplyEnterpriseFilter
|
||
- 不依赖 GORM Callback,权限过滤显式可见 ✅
|
||
|
||
**③ 任务队列解耦(Asynq)**
|
||
- 同步调用路径:Handler → Service → 提交 Asynq 任务
|
||
- 异步执行路径:Worker → Task Handler → Service/Store
|
||
- 支付回调触发的佣金计算走异步路径,不阻塞回调响应 ✅
|
||
|
||
**④ 外部服务封装(Gateway / 微信 / 富友)**
|
||
- Gateway HTTP Client 封装在 `internal/gateway/`
|
||
- 微信 SDK 封装在 `pkg/wechat/`
|
||
- 富友 SDK 封装在 `pkg/fuiou/`
|
||
- 外部依赖注入,可以独立替换 ✅
|
||
|
||
### 当前边界薄弱点(需要关注)
|
||
|
||
**⑤ Order Service 超大文件(Critical)**
|
||
- `internal/service/order/service.go` = **2365 行**
|
||
- 支付发起、支付回调、订单状态流转、幂等锁、钱包扣款全部耦合
|
||
- 任何一处改动都有全链路回归风险
|
||
- **建议:** 按职责拆分为子文件:`payment_service.go`、`callback_service.go`、`order_state.go`、`wallet_deduction.go`
|
||
|
||
**⑥ 轮询系统 asynqClient 依赖缺失(High)**
|
||
- `internal/task/polling_handler.go` 中实名激活通过 `Redis RPush` 降级实现,而非 Asynq 任务
|
||
- 架构偏差:同一 Worker 进程内用两套机制投递任务(Asynq + RPush)
|
||
- **建议:** 在 Worker Bootstrap 中注入 asynqClient,统一走 Asynq 路径
|
||
|
||
**⑦ C 端 Handler 直接访问 DB(Medium)**
|
||
- 方案 F-4:部分 C 端 Handler 绕过 Service 层直接访问 DB
|
||
- 破坏了分层边界,导致业务逻辑散落在 Handler 层
|
||
- **建议:** 迁回 Service 层,Handler 只做 HTTP 入参解析和响应封装
|
||
|
||
---
|
||
|
||
## 数据流方向
|
||
|
||
### 关键流 1:订单创建 + 支付 + 佣金链
|
||
|
||
```
|
||
用户发起购买
|
||
│
|
||
▼
|
||
Handler → 解析 DTO → 调用 OrderService.Create()
|
||
│
|
||
▼
|
||
OrderService.Create()
|
||
├── Redis 幂等键检查(业务键防重)
|
||
├── 分布式锁(RedisOrderCreateLockKey)
|
||
├── 二次检查(加锁后再查 Redis)
|
||
├── DB 事务:创建订单 + 冻结钱包余额
|
||
└── 提交 Asynq 支付超时任务(30min)
|
||
│
|
||
▼
|
||
支付回调(微信/富友)
|
||
│
|
||
▼
|
||
CallbackHandler → PaymentService.HandleCallback()
|
||
├── WHERE status=pending 条件更新(防重)
|
||
├── 更新订单状态为已支付
|
||
├── 解冻钱包余额 / 扣款
|
||
└── 提交 CommissionCalculation Asynq 任务
|
||
│
|
||
▼
|
||
Worker: CommissionCalculationTask
|
||
├── 查询代理层级路径(WITH RECURSIVE / parent_id 链)
|
||
├── 计算差价佣金链(每层代理差价 × 数量)
|
||
├── 计算一次性佣金(绑定规则)
|
||
├── DB 事务:写入 commission_record(幂等:unique(order_id, agent_id))
|
||
└── 更新代理钱包余额
|
||
```
|
||
|
||
### 关键流 2:IoT 卡轮询 + 实名激活
|
||
|
||
```
|
||
Polling Scheduler(独立 Goroutine)
|
||
│
|
||
├── 从 Redis Sorted Set 取到期卡片
|
||
│ key: polling:realname:queue
|
||
│
|
||
▼
|
||
投递 Asynq 任务 → Worker: PollingHandler
|
||
│
|
||
├── 调用 Gateway HTTP 接口拉取实名状态
|
||
├── 更新 iot_card.realname_status
|
||
│
|
||
▼
|
||
实名状态变为已认证 → 触发套餐激活
|
||
│
|
||
▼ (当前路径:RPush,待修复为 Asynq)
|
||
激活任务 → PackageService.ActivateByRealname()
|
||
├── 查找 status=3(待实名激活)套餐
|
||
├── 第一个主套餐 → status=1(激活)
|
||
├── 其余主套餐 → status=4(排队)
|
||
└── 加油包检查并激活
|
||
```
|
||
|
||
### 关键流 3:流量计费(当前方案 vs 改革方案)
|
||
|
||
```
|
||
当前(方案 E 改革前):
|
||
Gateway 上报流量 → 直接覆盖写 current_month_usage_mb
|
||
问题:自然月由上游归零,历史数据被破坏
|
||
|
||
改革后(方案 E):
|
||
Gateway 上报流量增量
|
||
│
|
||
▼
|
||
Redis 增量累加(今日流量缓冲)
|
||
│
|
||
每日凌晨批任务 → 写入 tb_card_daily_usage(日粒度记录)
|
||
│
|
||
查询层:Redis 今日数据 + DB 历史数据 合并返回
|
||
优点:历史数据不可变,查询范围可控
|
||
```
|
||
|
||
### 关键流 4:多租户数据权限
|
||
|
||
```
|
||
HTTP 请求 → Auth Middleware
|
||
│
|
||
├── 解析 JWT/Redis Token
|
||
├── 查询用户 user_type, shop_id, enterprise_id
|
||
├── GetSubordinateShopIDs()(WITH RECURSIVE,Redis 缓存 30min)
|
||
└── 写入 UserContextInfo 到 context.Context
|
||
│
|
||
▼
|
||
Store 层查询
|
||
├── Agent 用户 → ApplyShopFilter(shopIDs)
|
||
│ WHERE shop_id IN (当前+下级)
|
||
├── Enterprise 用户 → ApplyEnterpriseFilter(enterpriseID)
|
||
│ WHERE enterprise_id = X
|
||
└── SuperAdmin/Platform → 不过滤
|
||
```
|
||
|
||
---
|
||
|
||
## 架构模式
|
||
|
||
### 模式 1:两阶段幂等防重(订单创建)
|
||
|
||
**What:** Redis 业务键 + 分布式锁双重防护,防止并发创建重复订单
|
||
**When:** 任何创建类写操作(订单、提现、激活任务)
|
||
**Trade-offs:** 增加 2~3 次 Redis 往返,换取金融级安全
|
||
|
||
```go
|
||
// Step 1: Redis GET 快速检测
|
||
val, err := redis.Get(ctx, idempotencyKey).Result()
|
||
if err == nil && val != "" { return existingResult }
|
||
|
||
// Step 2: SetNX 分布式锁
|
||
locked, _ := redis.SetNX(ctx, lockKey, now, lockTTL).Result()
|
||
if !locked { return ErrTooManyRequests }
|
||
defer redis.Del(ctx, lockKey)
|
||
|
||
// Step 3: 加锁后二次检测(防止锁等待期间重复创建)
|
||
val, err = redis.Get(ctx, idempotencyKey).Result()
|
||
if err == nil && val != "" { return existingResult }
|
||
|
||
// Step 4: 执行业务逻辑...
|
||
// Step 5: 标记成功
|
||
redis.Set(ctx, idempotencyKey, resultID, ttl)
|
||
```
|
||
|
||
### 模式 2:条件更新防并发(状态流转)
|
||
|
||
**What:** `WHERE status = expected_status` 的条件 UPDATE,RowsAffected 判断
|
||
**When:** 支付回调、套餐激活、订单状态变更等有明确状态机的场景
|
||
**Trade-offs:** 需要数据库层有索引支持,效率高但依赖状态设计的正确性
|
||
|
||
```go
|
||
result := tx.Model(&model.Order{}).
|
||
Where("id = ? AND payment_status = ?", orderID, PaymentStatusPending).
|
||
Updates(map[string]any{"payment_status": PaymentStatusPaid})
|
||
if result.RowsAffected == 0 {
|
||
// 已被处理或并发冲突,根据当前状态决定返回
|
||
}
|
||
```
|
||
|
||
### 模式 3:Redis Sorted Set 驱动轮询调度
|
||
|
||
**What:** 以下次轮询时间为 Score,ICCID 为 Member,定时扫描到期项投递 Asynq 任务
|
||
**When:** 需要"不同间隔、海量卡片"的轮询调度场景
|
||
**Trade-offs:** 比 cron 更灵活,内存占用与卡片数量正相关;Redis 重启需重建队列
|
||
|
||
```go
|
||
// 投入轮询队列(Score = 下次轮询 Unix 时间戳)
|
||
redis.ZAdd(ctx, "polling:realname:queue", redis.Z{
|
||
Score: float64(nextPollAt.Unix()),
|
||
Member: iccid,
|
||
})
|
||
|
||
// Scheduler 每秒扫描
|
||
members := redis.ZRangeByScore(ctx, key, &redis.ZRangeBy{
|
||
Min: "-inf",
|
||
Max: strconv.FormatInt(time.Now().Unix(), 10),
|
||
Limit: &redis.Limit{Count: batchSize},
|
||
})
|
||
// 投递 Asynq 任务...
|
||
```
|
||
|
||
### 模式 4:多级佣金链计算(向上遍历)
|
||
|
||
**What:** 从发生订单的代理出发,沿 parent_id 向上遍历,逐级计算差价或固定佣金
|
||
**When:** 每笔订单支付成功后触发(异步任务)
|
||
**Trade-offs:** 当前 parent_id 邻接表实现,层级 7 层时 WITH RECURSIVE 性能尚可;超 10 层或高并发时需物化路径优化
|
||
|
||
```go
|
||
// 当前实现:DB 递归查询代理链(WITH RECURSIVE 或逐级查询)
|
||
// 建议:超 1000 TPS 时改为物化路径 + Redis 缓存代理链
|
||
func (s *Service) CalculateCommissionChain(ctx context.Context, orderID uint) error {
|
||
order := fetchOrder(ctx, orderID)
|
||
agentChain := fetchAncestorChain(ctx, order.SellerShopID) // 向上遍历
|
||
for i, agent := range agentChain {
|
||
diff := agent.SellPrice - agent.CostPrice
|
||
writeCommissionRecord(ctx, tx, order.ID, agent.ShopID, diff)
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 构建顺序建议
|
||
|
||
**原则:** 优先修复已存在但断裂的主链路,再扩展新功能,最后优化架构
|
||
|
||
```
|
||
阶段 0 — 主链路修复(P0,当前 MVP 阶段的首要目标)
|
||
│
|
||
├── 1. 实名常量统一(A-1)→ 解锁整个实名链路
|
||
├── 2. C 端实名校验(A-2)依赖 A-1
|
||
├── 3. 轮询 Handler 注入 asynqClient(A-3)→ 修复架构偏差
|
||
├── 4. 充值回调购包触发 + 佣金补全(A-4)→ 核心收入链路
|
||
├── 5. 代购订单金额修正(A-5)→ 佣金归零问题
|
||
└── 6. 并发校验修复(A-7, C-3)→ 提现/激活配置并发
|
||
|
||
阶段 1 — 功能补全(参考方案 B/C/D/H/J)
|
||
│
|
||
├── 企业端权限完善(B-1, B-2)
|
||
├── 提现/审批流程完善(C-1, C-2)
|
||
├── 设备体系完善(D-0 ~ D-3)
|
||
└── 轮询系统小修(H-1 ~ H-4)
|
||
|
||
阶段 2 — 流量计费改革(方案 E,独立窗口)
|
||
│
|
||
├── 新建 tb_card_daily_usage(迁移)
|
||
├── Redis 增量缓存层
|
||
└── 查询层适配(双段数据合并)
|
||
|
||
阶段 3 — 退款体系(方案 I)
|
||
│
|
||
├── 退款模型 + 7 个接口
|
||
└── 佣金钱包反向扣减
|
||
|
||
阶段 4 — Order Service 拆分(架构改善)
|
||
│
|
||
├── payment_service.go(支付发起)
|
||
├── callback_service.go(回调处理)
|
||
├── order_state.go(状态流转)
|
||
└── wallet_deduction.go(钱包操作)
|
||
```
|
||
|
||
**组件依赖关系:**
|
||
|
||
```
|
||
IoT卡状态 → 实名认证 → 套餐激活 → 流量计费 → 订单计算
|
||
│ │ │
|
||
▼ ▼ ▼
|
||
Gateway 数据轮询 Commission
|
||
集成层 调度层 计算层
|
||
```
|
||
|
||
---
|
||
|
||
## 扩展挑战与 SaaS 化瓶颈
|
||
|
||
### SaaS 化时会成为瓶颈的当前决策
|
||
|
||
| 当前决策 | SaaS 化面临的问题 | 迁移路径 |
|
||
|---------|-----------------|---------|
|
||
| 单一 PostgreSQL 数据库 | 所有"租户"(shop)共享同一 DB | 添加 `tenant_id` 列 + RLS,或 Schema 隔离 |
|
||
| GORM 数据过滤基于 shop_id | 过滤逻辑散布于 54 个 Store 文件 | 统一 Tenant Context 注入层,确保覆盖率 |
|
||
| Config 嵌入二进制 | 多租户需动态配置(微信AppID/支付商户号) | 已有 `tb_wechat_config`,需完全消除环境变量硬依赖 |
|
||
| 单进程 Worker | 一个 Worker 处理所有租户的轮询/佣金 | 按租户分队列;大租户独立 Worker |
|
||
| parent_id 邻接表代理层级 | 跨租户代理关系查询膨胀 | 加 `tenant_id` 隔离;超 5 万代理考虑物化路径 |
|
||
| commission_calculation 单服务 | 高 TPS 下单文件 653 行线性计算 | 异步 + 批量写入;超 1000 TPS 考虑 Flink |
|
||
|
||
### 各规模架构调整
|
||
|
||
| 规模 | 架构方案 |
|
||
|------|---------|
|
||
| 当前(< 100 代理,< 1000 卡)| 当前单体完全够用,重点是修复断链 |
|
||
| 成长期(1000+ 代理,10万+ 卡)| Worker 分队列 + 优化轮询 SortedSet 分片 |
|
||
| SaaS 初期(多客户,共享平台)| 添加 tenant_id 隔离层;动态支付配置;统一 OpenAPI 网关 |
|
||
| SaaS 规模(每客户数万卡)| Schema 隔离 or DB 隔离;独立 Worker 进程 per 大客户 |
|
||
| 高并发计费(> 5000 TPS)| 引入消息队列(Kafka)缓冲计费事件;离线批处理结算 |
|
||
|
||
### 第一个会触发的瓶颈:轮询调度
|
||
|
||
- **现状:** Redis Sorted Set + Asynq 混合投递,Worker 单机并发
|
||
- **触发条件:** 超过 5 万张活跃卡,每卡 5 分钟轮询一次 = ~167 TPS 持续 Gateway 请求
|
||
- **修复方向:** Gateway 并发限速配置 + 批量 API 合并 + Sorted Set 分片(多个 queue key)
|
||
|
||
### 第二个会触发的瓶颈:佣金计算的 DB 递归查询
|
||
|
||
- **现状:** `WITH RECURSIVE` 或逐级 parent_id 查询,最深 7 层
|
||
- **触发条件:** 单日 > 1 万笔订单,并发处理时 DB CPU 飙升
|
||
- **修复方向:** 代理链 Redis 缓存(shop_id → ancestor_chain);写入时物化路径 `path` 字段
|
||
|
||
### 第三个会触发的瓶颈:Order Service 耦合带来的发布风险
|
||
|
||
- **现状:** 2365 行,支付/回调/钱包全耦合
|
||
- **触发条件:** 添加新支付方式(富友小程序)或退款逻辑时,改动影响范围不可控
|
||
- **修复方向:** 拆分子文件(见构建顺序阶段 4),不需要跨进程拆分
|
||
|
||
---
|
||
|
||
## 反模式警告
|
||
|
||
### 反模式 1:在支付回调中同步计算佣金
|
||
|
||
**What:** 支付回调 Handler 直接在回调请求的生命周期内计算完整的多级佣金链
|
||
**Why bad:** 回调超时 → 第三方重推 → 佣金重复计算;而且 Gateway 通常要求快速响应(3s 内)
|
||
**Do this instead:** 回调只更新订单状态,通过 Asynq 任务异步计算佣金(当前架构已正确实现)
|
||
|
||
### 反模式 2:代理层级递归查询不加缓存
|
||
|
||
**What:** 每次数据权限过滤都调用 `WITH RECURSIVE` 查下级 shop_id
|
||
**Why bad:** 高并发下递归查询是 DB 杀手;7 层 × 每层 N 个子节点 = 指数级扫描
|
||
**Do this instead:** `GetSubordinateShopIDs` 结果 Redis 缓存 30 分钟(当前已实现),注意缓存失效策略
|
||
|
||
### 反模式 3:流量数据直接被上游覆盖写
|
||
|
||
**What:** Gateway 上报当月累计流量 → 直接 UPDATE current_month_usage_mb
|
||
**Why bad:** 上游自然月归零时,历史用量记录丢失;无法回查历史;无法审计计费
|
||
**Do this instead:** 日粒度缓冲(方案 E):增量写入 `tb_card_daily_usage`,查询层合并 Redis + DB
|
||
|
||
### 反模式 4:把租户隔离硬编码在每个 Store 文件
|
||
|
||
**What:** 54 个 Store 文件各自调用 ApplyShopFilter,过滤逻辑分散
|
||
**Why bad:** 新增 Store 文件时容易遗漏;SaaS 化时难以统一改造
|
||
**Do this instead:** MVP 阶段保持现状(显式>隐式);SaaS 化时考虑统一 TenantContext 注入层 + 强制 lint 检测
|
||
|
||
### 反模式 5:Worker 内两套任务投递机制
|
||
|
||
**What:** 轮询实名激活通过 `Redis RPush` 投递,其他任务走 Asynq
|
||
**Why bad:** 两套消费机制,Asynq 的可观测性/重试/超时管理对 RPush 任务无效
|
||
**Do this instead:** Worker Bootstrap 注入 `asynq.Client`,统一走 Asynq(方案 A-3)
|
||
|
||
---
|
||
|
||
## 集成点分析
|
||
|
||
### 外部服务
|
||
|
||
| 服务 | 集成模式 | 关键注意点 |
|
||
|------|---------|-----------|
|
||
| 运营商 Gateway | 同步 HTTP 调用(`internal/gateway/`) | Gateway 宕机时需降级;速率限制;超时设置 |
|
||
| 微信支付(JSAPI/H5)| PowerWeChat SDK | 配置已迁移至 `tb_wechat_config`,但 OAuth 仍读环境变量(待修复) |
|
||
| 富友支付 | 自研 SDK(pkg/fuiou/) | SDK 完整,主调接口仍留桩(方案 J-1)|
|
||
| 联通云 OSS | S3 兼容 SDK | 预签名 URL 上传,异步导入任务 |
|
||
|
||
### 内部模块边界
|
||
|
||
| 边界 | 通信方式 | 注意事项 |
|
||
|------|---------|---------|
|
||
| API → Worker | Asynq 任务队列(Redis) | 任务投递幂等;失败重试需要业务幂等保证 |
|
||
| Order ↔ Commission | 异步(支付回调完成后投递任务) | 不能同步等待佣金计算完成 |
|
||
| Package ↔ IoT Card | 同步(Service 层直接调用) | 套餐激活时需持有卡信息,单事务 |
|
||
| Polling ↔ Gateway | 同步 HTTP(Worker 内) | 限速;超时;Gateway 不可用时不应导致整个轮询系统崩溃 |
|
||
| Auth ↔ RBAC | 同步 Redis + DB(中间件层) | SubordinateShopIDs 缓存是性能关键 |
|
||
|
||
---
|
||
|
||
## 架构变更的高风险区
|
||
|
||
基于当前代码分析,以下区域变更风险最高,需要在 roadmap 中单独规划:
|
||
|
||
| 区域 | 风险原因 | 建议处理方式 |
|
||
|------|---------|------------|
|
||
| `internal/service/order/service.go` | 2365 行,全链路耦合 | 先修复 Bug,再在低风险时拆分 |
|
||
| 流量计费体系(方案 E) | 涉及 DB 迁移 + Redis 架构 + 查询兼容 | 单独发布窗口,充分测试迁移脚本 |
|
||
| 支付配置(微信/富友切换)| 半迁移状态(环境变量 vs DB 配置同时存在)| 明确单一配置源后再添加新支付方式 |
|
||
| 轮询系统(Polling Scheduler)| RPush 降级路径 + asynqClient 缺失 | A-3 修复后,逐步迁移到统一 Asynq 路径 |
|
||
| 提现并发逻辑(A-7, C-3)| 并发锁逻辑不完整,线上可能已有脏数据 | 修复时需同步修复历史数据 |
|
||
|
||
---
|
||
|
||
## Sources
|
||
|
||
- 当前代码库深度分析(2026-03-27):`internal/service/`, `internal/store/postgres/`, `internal/task/`, `internal/routing/`
|
||
- 多层级佣金系统架构设计(TechNova,2026-02-28):物化路径 vs 邻接表 vs 闭包表对比,CAP 权衡,批流一体
|
||
- Multi-Tenant SaaS Isolation(AverageDevs,2026-01-25):pooled tables vs schema per tenant,Row Level Security,noisy neighbor 防护
|
||
- Postgres Multitenancy 2025(DebuggAI):RLS vs Schema vs 独立 DB 性能对比
|
||
- Go Worker Pool + Asynq 并发控制(BackendBytes,OneUptime,2026):任务队列分区,并发控制
|
||
|
||
---
|
||
|
||
*Architecture research for: IoT 卡管理平台(君鸿卡管系统)*
|
||
*Researched: 2026-03-27*
|