数据库架构¶
KanjiIQ使用PostgreSQL 15作为主数据存储,部署在Kubernetes集群内,具有持久化存储。
模式概览¶
erDiagram
users ||--o{ study_sessions : has
users ||--o{ quiz_results : has
users ||--o{ test_results : has
kanji ||--o{ quiz_results : referenced_in
vocabulary ||--o{ quiz_results : referenced_in
users {
uuid id PK
text email
text password_hash
jsonb preferences
jsonb stats
timestamp created_at
}
kanji {
uuid id PK
text character
int jlpt_level
jsonb meanings
jsonb readings
text example_sentences
}
vocabulary {
uuid id PK
text expression
text reading
int jlpt_level
jsonb meanings
text part_of_speech
}
locale_configs {
uuid id PK
text locale_code
text[] default_languages
text[] available_languages
}
regional_analytics {
uuid id PK
text country_code
text request_path
text user_agent
text device_type
boolean is_suspicious
int response_status
timestamp created_at
}
ip_blocklist {
uuid id PK
text ip_address
text reason
text blocked_by
timestamp expires_at
boolean is_active
}
多语言内容存储¶
KanjiIQ使用PostgreSQL的JSONB列存储翻译,而不是单独的翻译表。这提供了灵活的、无模式的多语言存储:
// kanji.meanings column
{
"en": "mountain",
"es": "montaña",
"fr": "montagne",
"ja": "やま",
"pt": "montanha",
"ar": "جبل",
"zh-CN": "山"
}
为什么选择JSONB?
- 添加新语言时无需模式迁移
- 单次查询即可获取某个汉字的所有翻译
- PostgreSQL JSONB操作符支持高效的按语言查询
- 可使用GIN索引对翻译进行全文搜索
Kubernetes存储¶
PostgreSQL作为Kubernetes Deployment运行,使用PersistentVolumeClaim:
# k8s/02-postgres-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-pvc
namespace: jlpt-kanji
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
数据库不对集群外部暴露——只有后端Pod可以通过jlpt-postgres Service的5432端口访问。
关键设计决策¶
UUID主键¶
所有表使用UUID主键而非自增整数。这支持:
- 分布式ID生成(无需中心序列)
- API中安全暴露ID(不可猜测)
- 未来多区域复制时无ID冲突
级联删除¶
外键使用ON DELETE CASCADE来维护引用完整性。删除用户会自动删除其学习会话、测验结果和考试结果。
用户偏好存储为JSONB¶
用户偏好和统计数据存储为JSONB而非固定列:
// users.preferences
{
"defaultLanguages": ["en", "pt", "es"],
"studyLevels": ["N5", "N4"],
"showAllLanguages": false
}
// users.stats
{
"totalKanjiStudied": 245,
"averageScore": 78.5,
"streakDays": 12
}
这避免了每添加新偏好或统计项时进行模式迁移。
备份策略¶
数据库遵循3-2-1备份规则:
- 3份数据副本(在线 + 2份备份)
- 2种不同存储介质(PVC + 对象存储)
- 1份异地副本(Hetzner Object Storage)
每日pg_dump导出保留30天。详见部署章节了解运维详情。