news 2026/3/30 19:18:55

自动化毕设选题系统实战:基于规则引擎与协同过滤的可扩展架构

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
自动化毕设选题系统实战:基于规则引擎与协同过滤的可扩展架构


自动化毕设选题系统实战:基于规则引擎与协同过滤的可扩展架构

写在前面:去年 5 月,我帮学院把毕设选题从“微信群抢题”搬到线上,两周内用 Python 搭了一套可灰度、可回滚、可压测的自动化选题服务。上线当天 1200 名同学并发提交,峰值 QPS 3 200,零超卖、零重复。今天把踩过的坑和代码全部摊开,供下一届同学抄作业。

也欢迎直接拉到文末,把仓库 clone 下来跑一遍单元测试,再思考“没有历史数据时怎么冷启动推荐”。如果你能给出比“随机推荐”更好的方案,欢迎 PR。


1. 传统流程的四大痛点

  1. 并发竞争:抢题瞬间,几百人同时点“提交”,MySQL 行锁排队,页面 504。
  2. 冷启动:新生第一次选题,没有行为日志,协同过滤全是空矩阵。
  3. 公平性缺失:手速党秒抢热门题,慢网同学只能捡“剩”。
  4. 审计困难:导师临时加名额、教务手动改库,事后无法溯源。

一句话:人工 + 单体 + 无锁 = 高并发下的灾难现场。


2. 技术选型:规则引擎与推荐算法如何拍板

维度Drools自研轻量 DSL协同过滤内容相似度
学习成本高,引入 FACT 模型低,Python 链式判断需要历史矩阵需要题目文本特征
灵活度热更新 drl 文件发版重启即可冷启动无数据可结合 Jieba+TF-IDF
性能规则多≈1 ms1000 条规则 <0.2 ms矩阵稀疏后 <5 ms向量检索 <10 ms
运维需 KIE Server无额外依赖Redis 存矩阵Redis 存向量

结论:

  • 业务规则(导师配额、跨专业限制):用自研 DSL,写到 yml,规则变更随配置中心热更。
  • 推荐排序(学生兴趣):用“轻量协同过滤 + 内容相似度”混合,解决冷启动。
  • 规则与推荐解耦,前者在rule-service,后者在rec-service,通过 gRPC 通信,互不影响扩缩容。

3. 核心实现:Python 搭建选题服务

整体架构图:

3.1 锁定与幂等设计

  1. 学生点击“提交” → 后端生成order_token = hash(student_id + topic_id + nonce)
  2. 先写 Redis 分布式锁:SETNX lock:topic:{topic_id} {order_token} EX 5
  3. 锁成功后,把订单写入 MySQL 唯一索引 `(student_id, topic_id),status=PRE。
  4. 释放锁使用 Lua Script,保证“只有自己能解自己的锁”。

伪代码:

def submit_topic(student_id, topic_id): order_token = uuid4() lock_key = f"lock:topic:{topic_id}" ok = redis.set(lock_key, order_token, nx=True, ex=5) if not ok: raise Conflict("手慢无") try: dao.insert_order(student_id, topic_id, status="PRE") except IntegrityError: # 幂等:重复提交直接返回成功 return {"code": 0, "msg": "已选过"} finally: # 用 Lua 保证原子 lua = """ if redis.call("GET",KEYS[1])==ARGV[1] then return redis.call("DEL",KEYS[1]) else return 0 end """ redis.eval(lua, 1, lock_key, order_token) return {"code": 0, "msg": "选题成功"}

3.2 回滚机制

导师拒收、学生改主意,需要回滚。

  • 订单表加version乐观锁,状态机:PRE → CONFIRM → ROLLBACK。
  • 回滚时把topicremain+1,并删除 Redis 中该学生缓存的推荐列表,保证下次请求重新算。

4. 完整可运行示例(精简版)

项目结构:

auto_topic/ ├── app.py # Flask 入口 ├── service/ │ ├── rule.py # 规则 DSL 解析 │ ├── rec.py # 协同过滤 │ └── order.py # 订单事务 ├── tests/ │ └── test_concurrent.py └── script/ └── jmeter.jmx # 压测脚本

核心入口app.py

from flask import Flask, request, jsonify from service.order import submit_topic from service.rec import get_recall_list from service.rule import check_rule app = Flask(__name__) @app.post("/topic/submit") def topic_submit(): data = request.json student_id = data["student_id"] topic_id = data["topic_id"] # 1. 规则校验 if not check_rule(student_id, topic_id): return jsonify(code=403, msg="不符合选题规则"), 403 # 2. 提交订单 return jsonify(**submit_topic(student_id, topic_id)) @app.get("/topic/recommend") def topic_recommend(): student_id = request.args.get("student_id") return jsonify(data=get_recall_list(student_id)) if __name__ == "__main__": app.run(host="0.0.0.0", port=8000, threaded=True)

service/rec.py冷启动兜底:

import random, redis, json r = redis.Redis() def get_recall_list(student_id): # 优先读协同过滤 cf_key = f"cf:{student_id}" cf_list = r.get(cf_key) if cf_list: return json.loads(cf_list) # 冷启动:读内容相似度 Top10,再随机打散 content_key = f"content:{student_id}" content_list = r.zrevrange(content_key, 0, 9) if content_list: return [int(t) for t in content_list] # 仍为空,随机兜底 all_topics = r.zrevrange("all", 0, -1) return random.sample([int(t) for t in all_topics], k=10)

Clean Code 要点:

  • 函数长度 < 30 行,只做一件事。
  • 统一返回结构{code, msg, data},前端好封装。
  • 所有魔法值(锁超时 5s、随机 10 条)提到settings.py,方便压测调参。

5. 性能与安全

5.1 JMeter 压测结果

硬件:4C8G 容器单实例,后端 + Redis 同机部署。

场景:1200 并发用户,1 秒内起压,每人一次提交。

指标:

  • 平均 RT 63 ms
  • P99 110 ms
  • 错误率 0 %
  • 吞吐量 3 200 req/s(比旧系统 900 req/s 提升 3.5 倍)

5.2 Redis 分布式锁可靠性

  • 锁过期 5 s,业务 SQL 平均 15 ms,远小于过期时间。
  • 采用order_token唯一值 + Lua 脚本,杜绝“误删别人锁”。
  • Redlock 争议:单实例已满足学院量级;若跨机房,可升级redlock-py

5.3 防刷策略

  • 接口网关层(Kong)限流:同一 IP 10 rps,超出直接 429。
  • 业务层兜底:学生维度 1 分钟最多 5 次提交,用 RedisINCR+EXPIRE
  • 验证码:首次进入选题页加载图形验证码,防止脚本批量刷推荐列表。

6. 生产环境避坑指南

  1. 时间窗口配置
    把“选题开始、结束、导师审核”三段时间写进数据库,服务启动即缓存,避免硬编码。教务临时调时间,只需改表,不用发版。

  2. 导师配额超卖
    不要先SELECT remainUPDATE,高并发下必超卖。
    正确姿势:
    UPDATE topic SET remain = remain - 1 WHERE id = ? AND remain > 0
    返回影响行数 =1 才表示扣减成功,否则回滚订单并提示“已满”。

  3. 学生误操作恢复
    提供“一键撤选”按钮,状态机改为 PRE → CANCEL,并remain+1
    记录op_log表,字段(student_id, topic_id, from_status, to_status, op_uid, ctime),方便教务审计。

  4. 灰度发布
    选课系统一年只用一次,但流量集中。上线前用 Nginx 按 Cookie 灰度 10% 流量,观察错误率,再全量。

  5. 监控告警

    • Prometheus 采集order_status_total各状态计数,突增可预警。
    • 锁等待时间用redis_slowlog监控,超过 1 ms 即打印。

7. 留给读者的思考题

没有历史选题数据时,协同过滤就是空矩阵。除了“随机分配”和“按 GPA 排序”,你还能想到哪些零数据冷启动方案?

  • 用问卷采集学生关键词,再用内容相似度召回?
  • 把导师研究方向做 Embedding,与学生简历文本做语义匹配?
  • 或者干脆把第一次选题当做多臂老虎机,用 UCB 策略探索?

动手把代码跑通,再把你想到的冷启动策略提交 PR,让下一届学弟妹不被“抢题”支配。


版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/15 23:59:19

[技术突破] 跨硬件CUDA运行方案:非NVIDIA显卡的计算革命

[技术突破] 跨硬件CUDA运行方案&#xff1a;非NVIDIA显卡的计算革命 【免费下载链接】ZLUDA CUDA on Intel GPUs 项目地址: https://gitcode.com/GitHub_Trending/zl/ZLUDA 副标题&#xff1a;基于兼容性层的异构计算开源方案——让CUDA程序在Intel/AMD显卡上高效运行 …

作者头像 李华
网站建设 2026/3/26 8:54:24

高效创建Windows无人值守安装配置:unattend-generator实战指南

高效创建Windows无人值守安装配置&#xff1a;unattend-generator实战指南 【免费下载链接】unattend-generator .NET Core library to create highly customized autounattend.xml files 项目地址: https://gitcode.com/gh_mirrors/un/unattend-generator 在系统部署自…

作者头像 李华
网站建设 2026/3/27 15:19:11

智能客服系统实战:从架构设计到性能优化的全链路解析

背景痛点&#xff1a;高并发、方言与上下文的三重夹击 去年“618”大促&#xff0c;我们团队负责的智能客服在零点 3 分钟内涌入 42 万条消息&#xff0c;CPU 瞬间飙到 96%&#xff0c;P99 延迟从 400 ms 涨到 3.8 s&#xff0c;大量用户被转人工坐席&#xff0c;投诉率飙升。…

作者头像 李华
网站建设 2026/3/21 11:18:18

【效率工具】让Unity层级管理效率翻倍的黑科技

【效率工具】让Unity层级管理效率翻倍的黑科技 【免费下载链接】HierarchyDecorator Lightweight Unity Plugin transforming the Hierarchy into what it should be. Adds headers, styles, icons and more. 项目地址: https://gitcode.com/gh_mirrors/hi/HierarchyDecorato…

作者头像 李华
网站建设 2026/3/15 10:06:58

高效本地化金融数据处理:Mootdx实战指南

高效本地化金融数据处理&#xff1a;Mootdx实战指南 【免费下载链接】mootdx 通达信数据读取的一个简便使用封装 项目地址: https://gitcode.com/GitHub_Trending/mo/mootdx 在金融数据分析领域&#xff0c;数据获取与解析往往成为制约效率的关键瓶颈。通达信作为国内广…

作者头像 李华
网站建设 2026/3/26 1:50:29

软件供应链安全实战指南:使用Syft生成SBOM实现容器镜像审计

软件供应链安全实战指南&#xff1a;使用Syft生成SBOM实现容器镜像审计 【免费下载链接】syft CLI tool and library for generating a Software Bill of Materials from container images and filesystems 项目地址: https://gitcode.com/GitHub_Trending/sy/syft 在当…

作者头像 李华