GH GambleHub

iGaming内核中的DDD

iGaming平台是一个复杂的域系统,位于金融,娱乐和合规的交界处。DDD有助于保持复杂性:突出边界引用,捕获ubiquitous语言,通过聚合保护不变量,通过反腐败层简化集成,并通过域事件使系统行为透明。

1)域名映射和边界映射(战略设计)

建议的解构:
  • Player/KYC Context-注册、验证、负责任的游戏限制、KYC/AML状态。
  • Wallet/Ledger Context-资产负债表,备份,布线,多种货币性,课程。
  • Betting Context-投注/滴答作响,成对/结果,报价,计算(定位),取消。
  • Casino/Game Round Context-会话、回合、旋转、RTP控制、投注限制。
  • Bonus/Promo Context-奖金,旅行车,奖金收购和反抽奖规则。
  • Risk/Fraud Context-得分,行为提示,锁定/超时触发器。
  • Payments Context-存款/结算、支付网关状态、充电站事件。
  • Compliance/Reporting Context-向监管机构报告、制裁名单、审计。
  • Content/Provider Integration Context-与游戏提供商、目录、技术集成。状态。
  • Analytics/Read Models-产品阅读的投影和展示。
💡 跨域通信-通过域事件和异步命令;同步调用-仅在确实是域合同并且需要严格一致性的情况下。

2)Ubiquitous语言: 术语的核心

Player(玩家),Session(会议),GameRound(回合),Bet/Ticket(投注),

Ledger Entry(布线)、Hold/Reserve(储备金)、Settlement(计算)、

Bonus Credit / Bonus Balance, Wagering Requirement (Вейджер),

KYC Tier、Limit(存款/会话/损失)、Self-Exclusion、

Provider Game, RTP Window, Risk Flag, Compliance Case.

这些名称在代码,DB,文档,测试和接口中同样使用。

3)聚合和不变量(战术设计)

3.1 Wallet (Aggregate: `Wallet`)

不变量:
  • 平衡不会消失。
  • 备份+可用≤总余额。
  • Atomarn和Idempotent接线(通过"operation_id")。
命令/事件:
  • `Wallet.Reserve(amount, reason, op_id)` → `WalletReserved`
  • `Wallet.Commit(op_id)` → `WalletCommitted`
  • `Wallet.Rollback(op_id)` → `WalletRolledBack`

边界:Wallet不知道Bet/Bonus;它为布线和储备业务提供服务。

3.2 Bet/Ticket (Aggregate: `Bet`)

不变量:
  • 只有在活动报价窗口中才能接受投注;玩家/会话上限≤金额。
  • 在"定居"之后,状态被"最终化";仅通过具有明确审核的补偿性操作(void/recalc)允许重新计算。
命令/事件:
  • `Bet.Place(player_id, amount, price, op_id)` → `BetPlaced` (требует Wallet.Reserve)
  • `Bet.Settle (outcome, payout) '→ 'BetSettled'(需要Wallet.Commit/Release)
  • `Bet.Void(reason)` → `BetVoided`

边界:Bet不在Wallet中"爬行"-通过域命令/编排进行处理。

3.3 GameRound (Aggregate: `Round`)

不变量:
  • 每个旋转/回合都有独特的"round_id"和相关的投注/获胜金额。
  • RTP窗口不超过指定的阈值(在提供程序级别+本地规则)。
事件:
  • `Round.Started`, `Round.Staked`, `Round.Resulted`, `Round.Closed`.

3.4 Bonus (Aggregate: `BonusGrant`)

不变量:
  • Vager仅从有效周转中减少,奖金注销不会进入借记。
  • 根据优先权规则,不可能同时注销奖金和实际资金。
事件:
  • `BonusGranted`, `BonusWagered`, `BonusExpired`, `BonusConverted`.

4)编排,传奇和连贯性

同步(CP):接受利率和资金储备-单一途径:'Bet。Place` → `Wallet.Reserve'(通过带截止日期的域命令/编曲器)。
异步(EC):通过事件+outbox计算利率、累积奖金、分析。
TCC变体:"TryReserve"(扑克),"Confirm"(commit),"Cancel"(rollback)用于货币效果。
相同性:所有团队都携带"operation_id",用户携带"inbox"。

5)反腐败层(ACL)和集成

提供者ACL:将提供商"SpinResult","BonusWin"事件广播到内部的"Round"。Resulted`, `BonusWagered`.模式和版本-在ACL中。
PSP ACL:正常化支付状态,通过"psp_tx_id"的幂等,翻译为"LedgerEntry"。
法规遵从性ACL:在外部环境中与制裁/RER列表集成;仅归一化的"ScreeningUpdated"进入域内。

规则:外部字典/格式不会"渗入"内核。

6)投影和阅读模型

播放器配置文件阅读模型:KYC状态、限制、活动奖金、新鲜交易。
Balances阅读模型:UI/市场营销的快速阅读;来源-"Wallet"事件。
Bet History阅读模型:按日期/游戏划分;来源-"BetPlaced/Settled"。
Compliance Reports: Tenant/Region的实例化视图。

所有投影都是具有转换和"as_of/freshness"的等效的upsert's。

7)多特南特和多区域

所有关键实体都带有"tenant_id"和(如果需要)"区域"。
数据边界:玩家,钱包,赌注是"家庭"区域;仅跨区域汇总/报告。
公平性/配额:tenant的命令/秒限制和重复。
住宅/合规性:个人数据和布线不会离开该地区。

8)按上下文选择一致性(PACELC)

Wallet/Ledger-Strong/CP:线性布线,法定记录。
Bet acceptance-用于UI的同步确认(CP)+快速阅读模型。
定位/奖金/分析-具有确定性merge/补偿的 EC。
KYC/Compliance-状态可能是EC,但"锁定"规则是同步应用的。

9)域名事件: 合同和版本

最小字段集为:
json
{
"event_id": "uuid",
"event_type": "BetPlaced",
"occurred_at": "timestamp",
"tenant_id": "T123",
"aggregate_id": "BET-...-UUID",
"version": 7,
"payload": { "...domain fields..." },
"schema_version": "v3"
}
规则:
  • 背部/前向复合电路;通过"schema_version"演变。
  • 域更改事务中的"outbox";batchami与backoff发布。

10)带奖金的赌注流示例(言语序列)

1. `Bet.Place'(团队)→检查球员限制和→ 'Wallet奖金规则。Reserve(real+bonus_equiv, op_id)`

2. "BetPlaced"(事件)→ Read Model更新"开放投注"

3.提供程序发布结果→ ACL → 'Round。Resulted`

4.编曲器计算:'Bet。Settle(outcome,payout)` → `Wallet.Commit(op_id)'和,当获胜时,"BonusWagered "→可能的奖金转换为真实奖金。
5、"BetSettled" →历史和平衡投影,报告。

11)不变量与测试策略

关键不变量:
  • 钱包中所有"LedgerEntry"的总和等于资产负债表;没有负余额。
  • 在主动自我释放/冻结的KYC状态下不能接受出价。
  • Vager只能减小并且不会"减去"摆动。
  • Settlement不会更改已经最终的投注状态-仅通过"Void/Recalc"+补偿布线。
测试:
  • 基于财产的钱包和赌注不变性测试。
  • 溷沌轮廓:提供商延迟、PSP故障、outbox/DLQ重新分区。
  • 模式控制:事件迁移,后置投影。

12)遥测和审计

指标:PlaceBet/Reserve/Commit上的p95/p99,限值/CUS故障率,DLQ利率,redrive成功,lag投影。
Tracing: spans "komanda→agregat→outbox→konsyumer→proyektsiya"、"tenant_id"、"operation_id"、"saga_id"标签。
审计:与监管要求相当的不可变域活动日志。

13)存储方案(简化)

Wallet:


wallet(id, tenant_id, currency, balance, reserved, version)
ledger(id, wallet_id, amount, type, operation_id, occurred_at)
holds(id, wallet_id, amount, operation_id, expires_at, status)

Bet:


bet(id, tenant_id, player_id, amount, price, status, placed_at, settled_at, operation_id)

Bonus:


bonus_grant(id, tenant_id, player_id, amount, wager_left, status, expires_at)

在单元上进行转换("版本")将防止在竞争性记录下丢失更新。

14)命令示例API(伪)

http
POST /bets. place
{
"tenant_id":"T1",
"player_id":"P42",
"amount":"10. 00",
"price":"2. 1",
"operation_id":"op-uuid",
"context":{"game_id":"g777","channel":"web"}
}
→ 202 Accepted + BetPlaced

POST /wallets. reserve
{ "wallet_id":"W1", "amount":"10. 00", "operation_id":"op-uuid", "reason":"bet" }
→ 200 { "reserved_balance":"..." }

所有命令均以"operation_id"表示幂等,答案以"as_of"/"version"表示。

15)安全性和合规性

RLS/ACL:所有请求均在"tenant_id"上下文中,按角色进行访问。
PII最小化:将域事件与个人数据分开;DLQ/Logs中的伪装。
监管报告:在时间窗口中具有不可变哈希签名的投影。

16)典型错误

上下文之间的紧密连接(Wallet直接知道Bet/Bonus)。
在没有传奇/outbox的不同情况下进行双重写作→资产负债表和状态的不一致。
团队和用户缺乏相等性→电线/计算双倍。
提供商合同流向域模型(更难迁移)。
一个"巨型"单元(Player包括所有)锁定→,低通量。
没有显式不变式-无法验证和监视它们。

17)快速食谱

开始:记录优美的语言和上下文界限;记录不变量。
金钱:钱包/Ledger-CP,法定记录,TCC用于外部效果。
投注:同步接收+异步计算,全部通过事件和outbox;等效性无处不在。
奖金:一个单独的单元,具有明确的注销优先级和vager。
集成:始终通过ACL+模式/版本;核心没有"原材料"付费。
阅读:针对产品需求的投影/店面;SLA新鲜+"as_of"。
操作:不变量度量,DLQ/redrive花花公子,重生店面。

18)售前支票清单

  • 已定义了边界内容及其合同(命令/事件)。
  • 聚合物具有明显的不变性,反转和幂等指令。
  • 现金交易-通过TSS/严格的交易;已启用审计。
  • 整合-通过ACL进行电路转换和进化测试。
  • 引入outbox/inbox、DLQ和安全重做。
  • 投影实现了SLA的新鲜度,并具有拉格/稳定度量。
  • 符合多重限额/限额和数据驻留。
  • 可观察性:通过不变量对"komanda→sobytiye→proyektsiya"进行跟踪。
  • 文档:域语言,上下文图,事件花花公子。

结论

iGaming内核中的DDD是难度分离的学科:上下文的清晰边界,具有不变量的聚合,作为真理来源的事件,用于外部集成的ACL以及有意识的一致性选择。这种方法使该平台具有可扩展性,可靠性和适当的法规,加快了幻灯片的开发并降低了运营风险-即使流量、地理和产品线的快速增长也是如此。

Contact

联系我们

如需任何咨询或支持,请随时联系我们。我们随时准备提供帮助!

Telegram
@Gamble_GC
开始集成

Email — 必填。Telegram 或 WhatsApp — 可选

您的姓名 可选
Email 可选
主题 可选
消息内容 可选
Telegram 可选
@
如果填写 Telegram,我们也会在 Telegram 回复您。
WhatsApp 可选
格式:+国家代码 + 号码(例如:+86XXXXXXXXX)。

点击按钮即表示您同意数据处理。