15 · iGaming 行业知识¶
行业媒体:https://igamingbusiness.com/ · https://www.egr.global/ AWS 博彩架构:https://docs.aws.amazon.com/architecture-diagrams/latest/sports-betting-architecture/ 本文档专为运维技术人员理解业务背景而编写
1. 平台核心系统架构¶
系统组成¶
┌─────────────────────────────────────────────────────────┐
│ 前端层 │
│ H5 移动端 · Web · Native App · 第三方集成 iFrame │
└────────────────────────┬────────────────────────────────┘
│ HTTPS / WebSocket
┌────────────────────────▼────────────────────────────────┐
│ API 网关层 │
│ Nginx / AWS ALB ←→ Cloudflare WAF & CDN │
└──────┬──────────────┬──────────────────┬────────────────┘
│ │ │
┌──────▼──────┐ ┌─────▼──────┐ ┌────────▼───────┐
│ PAM 系统 │ │ 赔率引擎 │ │ 支付/钱包系统 │
│(账户管理) │ │(Sportsbook)│ │ │
└──────┬──────┘ └─────┬──────┘ └────────┬───────┘
│ │ │
┌──────▼──────────────▼──────────────────▼────────────────┐
│ 数据层 │
│ PostgreSQL(账户/交易) · Redis(赔率/Session/限流) │
│ Kafka(实时事件流) · S3/R2(日志/媒体文件) │
└─────────────────────────────────────────────────────────┘
2. PAM(玩家账户管理系统)¶
核心功能¶
用户注册与 KYC(身份验证)
- 文件上传(护照/身份证)
- 第三方 KYC 接口(Jumio/Onfido/Sum&Sub)
- 地理位置验证
账户管理
- 余额查询(可用/冻结/待结算)
- 交易历史
- 账户等级(VIP 体系)
- 自我限制(负责任博彩)
Session 管理
- JWT Token(短期,15分钟)
- Refresh Token(Redis 存储,30天)
- 多设备登录控制
运维关注点¶
# Session 失效问题(Redis 连接)
redis-cli -h $REDIS_HOST get "session:{session_id}"
redis-cli -h $REDIS_HOST ttl "session:{session_id}"
# 账户余额不一致(数据库事务)
SELECT user_id, balance, frozen_amount, pending_amount,
balance + frozen_amount + pending_amount as total
FROM wallets WHERE user_id = $1;
# KYC 队列积压(第三方 API 超时)
kubectl logs deployment/kyc-service -n production --tail=100 | grep ERROR
3. 赔率引擎(Sportsbook 核心)¶
数据流¶
第三方赔率数据源(Betradar/Sportradar)
↓ WebSocket / HTTP Feed
赔率接收服务(Feed Service)
↓ 数据处理 & 风控
Kafka Topic: odds-updates
↓
WebSocket 推送服务(广播给客户端)
↓ Redis Pub/Sub
在线用户(实时看到赔率变化)
运维关注点¶
# 赔率停止更新(最严重的问题之一)
# 检查 Feed 连接状态
kubectl logs deployment/feed-service -n production | grep "connection"
# 检查 Kafka 消费延迟
kafka-consumer-groups.sh --bootstrap-server $KAFKA_BROKER \
--describe --group odds-websocket-consumer
# Redis Pub/Sub 订阅者数量
redis-cli -h $REDIS_HOST pubsub numsub "odds-channel"
# 实时监控赔率更新频率(Prometheus)
# rate(odds_updates_total[1m]) < 10 → 告警
投注处理流程¶
用户提交投注请求
↓
验证用户 Session(Redis)
↓
检查用户余额(DB 悲观锁)
↓
验证赔率是否仍然有效(Redis 赔率缓存)
↓
锁定赔率、冻结投注金额
↓
写入投注记录(DB Transaction)
↓
推送 Kafka 事件(供风控、结算消费)
↓
返回 Bet Slip(投注凭条)
4. 多租户白标架构¶
技术实现¶
一套基础设施服务多个品牌(租户):
流量路由(通过 Host Header 区分):
brand1.com → 请求到达 Nginx → 转发到 Brand1 Backend
brand2.com → 请求到达 Nginx → 转发到 Brand2 Backend
数据隔离方式:
方案A(独立 Schema):PostgreSQL 每个租户独立 Schema
pros:数据完全隔离,迁移方便
cons:连接池压力大,表结构更新复杂
方案B(共享 Schema + tenant_id):所有表加 tenant_id 列
pros:资源利用率高,维护简单
cons:需要确保查询都带 tenant_id 过滤(避免数据泄露!)
Cloudflare SSL for SaaS(域名层隔离):
每个品牌的域名都指向同一个 Origin
Cloudflare 自动管理各品牌的 SSL 证书
Origin 通过 X-Custom-Hostname header 识别品牌
新客户开通 Checklist¶
# 1. Cloudflare Zone 配置(Terraform)
# 2. SSL 证书申请(Custom Hostname)
# 3. 数据库 Schema 初始化
# 4. Redis namespace 分配(key prefix: brand_id:xxx)
# 5. 后端服务配置(白标主题/Logo/颜色)
# 6. 支付通道对接(每个客户可能用不同 PSP)
# 7. 监控告警配置(Grafana Dashboard 复制)
5. 支付通道¶
常见支付类型¶
本地支付方式(东南亚市场重点):
菲律宾:GCash、PayMaya、7-Eleven 便利店
泰国:PromptPay、TrueMoney
越南:MoMo、ZaloPay
印尼:GoPay、OVO、Dana
国际支付:
Visa/Mastercard
Skrill、Neteller(电子钱包)
Crypto:USDT/TRC20(博彩行业广泛使用)
支付系统运维¶
# 支付失败排查
# 1. 检查 PSP(支付服务商)API 状态
curl -s https://status.stripe.com/api/v2/status.json | jq '.status.description'
# 2. 检查支付回调(Webhook)是否收到
grep "payment_callback" /var/log/app/payment.log | tail -50
# 3. 检查待处理支付(卡住的订单)
SELECT id, user_id, amount, status, created_at, updated_at
FROM payment_orders
WHERE status = 'pending' AND created_at < NOW() - INTERVAL '30 minutes'
ORDER BY created_at;
# 4. 手动触发支付状态同步
curl -X POST https://api.internal/admin/payments/sync-pending \
-H "Authorization: Bearer $ADMIN_TOKEN"
6. 合规 & 牌照技术要求¶
各牌照关键技术要求¶
| 牌照 | 数据驻留 | SSL 最低版本 | 日志保留 | RNG 认证 |
|---|---|---|---|---|
| MGA(马耳他) | 服务器必须在 EEA | TLS 1.2+ | 5年 | 必须 GLI/BMM |
| UKGC(英国) | 可在 UK 以外 | TLS 1.2+ | 3年 | 必须 |
| PAGCOR(菲律宾) | 菲律宾境内 | TLS 1.2+ | 5年 | 要求 |
| Curaçao | 无限制 | TLS 1.0+ | 2年 | 不强制 |
地理封锁实现(Cloudflare Workers)¶
// 根据 CF 提供的国家信息封锁
const BLOCKED_COUNTRIES = new Set(['CN', 'KP', 'IR', 'CU', 'SY', 'SD']);
const US_BLOCKED_STATES = new Set(['UT', 'WA']); // 未开放州
export default {
async fetch(request) {
const country = request.cf?.country;
const region = request.cf?.region; // 州/省
if (BLOCKED_COUNTRIES.has(country)) {
return Response.redirect('https://www.example.com/geo-blocked', 302);
}
if (country === 'US' && US_BLOCKED_STATES.has(region)) {
return Response.redirect('https://www.example.com/state-blocked', 302);
}
return fetch(request);
}
};
7. 负责任博彩(技术实现)¶
-- 自我限制功能(存储层)
CREATE TABLE self_exclusions (
user_id UUID NOT NULL,
type VARCHAR(20) NOT NULL, -- 'deposit_limit' / 'session_limit' / 'self_exclude'
value DECIMAL, -- 限额值
period VARCHAR(10), -- 'daily' / 'weekly' / 'monthly'
expires_at TIMESTAMP, -- NULL = 永久
created_at TIMESTAMP DEFAULT NOW()
);
-- 冷静期(自我排除后不能立即解除)
-- 通常要求 24-72小时 冷静期
8. 关键监控指标(业务层)¶
Grafana 必备仪表盘指标¶
投注类:
每分钟投注量(Bets per Minute)
投注成功率(应 > 99.5%)
平均投注响应时间(应 < 200ms p95)
赔率更新频率(应 > 10次/分钟/赛事)
财务类:
支付成功率(应 > 98%)
充值/提现量
待处理支付订单数(应接近0)
用户类:
在线用户数(WebSocket 连接数)
用户登录成功率
Session 活跃数
基础设施类:
API 错误率(5xx < 0.1%)
数据库连接池使用率(< 80%)
Redis 内存使用率(< 70%)
Cloudflare 请求量 & 缓存命中率
官方文档 & 行业资源¶
| 资源 | 链接 |
|---|---|
| AWS 博彩架构参考 | https://docs.aws.amazon.com/architecture-diagrams/latest/sports-betting-architecture/ |
| MGA 技术规范 | https://www.mga.org.mt/licensee-hub/technical-documentation/ |
| Cloudflare iGaming 案例 | https://www.cloudflare.com/case-studies/ |
| iGaming Business 行业媒体 | https://igamingbusiness.com/ |
| EGR 行业奖项 & 报告 | https://www.egr.global/ |
| Sportradar(赔率数据源) | https://sportradar.com/betting/ |
| SOFTSWISS 技术博客 | https://softswiss.com/resources/ |
最后更新:2025-04