Skip to content

v3.1.3

Latest

Choose a tag to compare

@pollybird pollybird released this 15 Oct 13:57
· 4 commits to main since this release

性能与并发健壮性版本(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.py 14 项场景测试(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 中提出的性能优化建议。