Repository navigation
性能与并发健壮性版本(GitCode issue #3 四项中危 M7-M10)
本版本针对 GitCode 仓库 issue #3 提出的四项性能与并发健壮性问题进行集中修复,无数据库结构变更、无新增依赖,覆盖代码重启即可生效。
M7 Setting 逐键查询写放大
单页渲染链路 Setting.get() 调用 20+ 次,每次一条 first() SQL,模板/上下文处理器叠加后写放大明显。
- 新增请求级整表缓存(
flask.g,app/models/setting.py::_request_cache_map):同请求首查整表建映射,后续读零 SQL set()写后失效当前请求,同请求内写后立即可见;get_dict()复用同一映射- 无应用上下文(CLI / 裸调用)回退逐键查询;缓存仅存活于单请求,多 worker 无一致性问题
M8 浏览量逐请求写事务 + 缓存窗口计数不增长
文章详情每次访问 viewed + 1 即 commit(),高并发下写库压力大;且整页缓存命中时视图体不执行,缓存 TTL 内(默认 900s)浏览量完全不增长。
- 改为缓存累加 + 合并回库:
_incr_view()把增量累加到缓存键article:viewed:pending(缓存不可用回落旧行为) - 新增
_flush_view_counts():以UPDATE ... SET viewed = viewed + n合并回库 - APScheduler 新增 60s 周期任务
zhycms_view_flush;多 worker(不启内置调度器)时由请求内阈值(累计 200 次)兜底触发 - 整页缓存命中路径显式调用
_incr_view(),修复缓存窗口内计数不增长 - 合并失败增量放回缓存不丢数;兜底 TTL 24h 防调度器长期停止时内存累积
M9 首页 N+1 查询
首页对 9 个行业区块 slug 逐个子查询(栏目 + 子栏目 + 文章各一条 SQL),叠加最新文章循环与导航树,单页 20+ 条 SQL。
- 收口为
_home_section_data()批量拉取:栏目一次IN、子栏目一次、跨栏目文章一次,共 3 条 SQL,内存分组取前 N,排序语义与原实现一致 Column.get_tree_cached()请求级缓存栏目树(导航 + 上下文处理器叠加只查一次)clear_content_cache()统一失效树缓存,栏目/文章 CRUD 后同请求立即读到新树
M10 用户名唯一性竞态
create_user 先查重后插入存在并发竞态,users.username 唯一索引兜底时 flush/commit 抛 IntegrityError 未捕获 → 500。
flush()与commit()均捕获IntegrityError,回滚并 flash「用户名已存在」业务错误
升级须知
- 无数据库结构变更、无新增依赖(APScheduler 已有),覆盖代码重启即可生效
- 浏览量统计语义变化:从「逐请求即时写库」变为「缓存累加 + 周期(约 60s)/ 阈值(200 次)合并」,计数为近似值(误差窗口 ≤ 60s 或 200 次);同时修复了开启整页缓存时计数不增长的缺陷
- 详见项目根目录
UPGRADE.md与CHANGELOG.md
测试与门禁
- 新增
tests/test_performance_m.py14 项场景测试(M7 SQL 计数与缓存失效、M8 批量合并/缓存页计数、M9 批量拉取 3 条 SQL/树缓存失效、M10 竞态回退/端点无 500) - 全量 360 项测试通过(v3.1.2 的 346 项 + 14 项新增)
scripts/check_release.py --version 3.1.3版本一致性检查通过scripts/check_constants.py常量门禁通过
致谢
感谢 GitCode 用户在 issue #3 中提出的性能优化建议。