新闻详情

新闻详情

首页 / 资讯中心 / 详情

Python在线选课系统从零开发:高并发抢课与防超卖实战

发布时间:2026/10/2 20:06:22来源:尧图网络
Python在线选课系统从零开发:高并发抢课与防超卖实战
每个学期选课那几天就是校务系统的年度大考。学生8点58分就开始刷页面9点整瞬间涌入热门课程半分钟内抢完紧接着各种明明显示成功却看不到课表的投诉单飞过来。我自己用Python完整做过一套在线选课系统从数据库设计到并发抢课处理、从后台管理到上线部署踩过不少坑也总结出一套可以复用的方案。这篇文章就把整个系统的实现思路、关键代码和避坑经验拆开讲清楚给准备做类似教务系统、预约系统的朋友一个直接能抄作业的参考。这套系统适合谁看想用Python做Web项目练手的同学会被安排在教务处系统开发的中小型项目负责人以及任何需要处理短时间内大量用户同时操作同一份数据这种场景的开发人员。本质上选课系统就是一个高并发写入的经典案例搞懂了它抢票、预约、秒杀类系统你都能触类旁通。1. 项目概述与需求拆解1.1 选课系统的核心业务场景在线选课系统说白了就是三类角色学生、教师、管理员。学生负责登录、浏览课程、选课退课、查自己的课表教师负责开设课程、填写课程信息、查看选课名单管理员做的是管用户、配系统、控制选课开放时间。听起来不复杂但真上手做麻烦全藏在边角里。最典型的就是热门课秒光问题一门通识课只有30个名额偏偏有300个学生在同一秒点了选课。如果你用最直白的写法——先查余量、再判断、再插入——那几乎必然超卖。我在第一版就栽在这上面后面老老实实补上了数据库锁和事务控制。另一个容易被忽略的是选课时间窗口。大多数学校不是全天开放选课而是分批次错峰开比如大三先选半小时大二再开。系统必须支持配置化的选课时段而不是把时间写死在代码里。这件事做不好每学期改代码改到怀疑人生。1.2 为什么选Python而不是Java或Node选Python做这类系统的核心理由只有一个开发效率。Django自带Admin后台、ORM、用户认证一个选课系统从零到能跑通全流程两个星期内完全可以搞定。同样的功能用Java Spring Boot做开发周期至少翻一倍对学生项目或者中小型学校的内部系统来说这个时间成本划不来。当然Python也不是没代价GIL导致的多线程瓶颈、高并发场景下的性能天花板都是客观存在的。但选课系统属于典型的读多、写少、峰值短应用峰值压力集中在开放选课的十几分钟。用Python加合适的架构完全扛得住没必要为一时的峰值去引入更重的技术栈。性能方面有个经验数值可以参考一台4核8G的服务器跑Django加Gunicorn加PostgreSQL不加Redis时大概能撑每秒200到300个选课请求加上Redis做缓存和队列之后每秒能到1000以上。一个年级几千人的学校这个量级绰绰有余。2. 系统架构与数据库设计2.1 整体架构Django PostgreSQL Redis我最终用的技术栈是Django 4.x加PostgreSQL 15加Redis 7前端用Django模板加Bootstrap部署在Linux上用Gunicorn和Supervisor托管。逐个说下选型理由。Django自带的User模型和Admin后台能省掉一大半重复工作用户认证、权限分组、表单处理全是现成的。PostgreSQL在事务和锁机制上比MySQL更完善SELECT ... FOR UPDATE、可串行化隔离级别这些能力正好是选课并发场景需要的。Redis用来做课程缓存、选课窗口配置缓存和抢课队列。可能有同学会问为什么不用FastAPIFastAPI性能确实更轻快但选课系统是业务逻辑密集、后台管理需求重的项目Django的全家桶开发体验明显优于FastAPI的拼积木模式。想尝鲜可以用FastAPI但求稳、求快、求省心Django是更稳妥的选择。2.2 数据库表结构设计选课系统的核心表就四张用户扩展表、课程表、选课记录表、选课时间窗口表。先把建表SQL贴出来再逐个说清楚关键决策。-- 用户扩展表Django默认auth_user之上做扩展 CREATE TABLE app_user_profile ( user_id INT PRIMARY KEY REFERENCES auth_user(id), student_no VARCHAR(20) UNIQUE, major VARCHAR(100), grade INT, role VARCHAR(10) DEFAULT student -- student/teacher/admin ); -- 课程表 CREATE TABLE app_course ( id SERIAL PRIMARY KEY, course_code VARCHAR(20) UNIQUE NOT NULL, course_name VARCHAR(100) NOT NULL, teacher_id INT REFERENCES auth_user(id), credit FLOAT DEFAULT 2.0, capacity INT NOT NULL DEFAULT 60, -- 总容量 selected_count INT NOT NULL DEFAULT 0, -- 已选人数 week_day INT, -- 1-7代表周一到周日 start_section INT, -- 起始节次 end_section INT, -- 结束节次 semester VARCHAR(20) NOT NULL, status VARCHAR(10) DEFAULT open, -- open/closed/full description TEXT ); -- 选课记录表 CREATE TABLE app_enrollment ( id SERIAL PRIMARY KEY, student_id INT REFERENCES auth_user(id), course_id INT REFERENCES app_course(id), enrolled_at TIMESTAMP DEFAULT NOW(), UNIQUE(student_id, course_id) ); -- 选课批次窗口表 CREATE TABLE app_select_window ( id SERIAL PRIMARY KEY, name VARCHAR(50) NOT NULL, -- 批次名称 grade INT NOT NULL, -- 面向年级 start_time TIMESTAMP NOT NULL, end_time TIMESTAMP NOT NULL, is_active BOOLEAN DEFAULT TRUE );表结构里有几个关键决策值得展开讲。selected_count字段必须在课程表里冗余一份而不是每次实时用COUNT(*)去统计。原因有两个第一选课时需要快速判断还剩几个名额实时统计在并发下既慢又容易产生幻读第二把计数放在课程表里配合事务锁就能在一条记录上完成检测容量、占用名额的原子操作。再留意一下capacity和selected_count两个字段而不是直接存remaining_count。因为查询还有没有空位只需要比较这两个字段如果只存剩余数每次处理选课成功和退课成功都要把整个操作封装成原子自增减反而容易在并发事务里互相覆盖。2.3 索引与查询优化选课高峰期的主要查询模式就两种按学期查课程列表查某学生已经选了的课。对应的索引至少要加CREATE INDEX idx_course_semester ON app_course(semester, status); CREATE INDEX idx_enrollment_student ON app_enrollment(student_id);这里有个容易被忽略的点登录日志表和验证码表的清理策略。我一开始没有做清理跑了一个学期日志表涨到了两个多GB备份时间肉眼可见地变长。后来加了定时任务每天凌晨清理90天前的记录问题立刻缓解。3. 核心功能实现与实操细节3.1 用户认证Django内置认证到底够不够用Django自带认证在中小型项目里完全够用登录、登出、Session管理都是现成的改一下登录模板就能用。但有两个地方必须自定义。第一个是登录保护。选课高峰期的登录请求量是平时的几十倍如果不限制暴力尝试服务器会非常难受。我用Django-simple-captcha做图形验证码再结合一个简单的失败次数限制同一个IP五分钟内失败超过5次锁定半小时。from django.core.cache import cache def check_login_attempts(ip): key flogin_fail_{ip} count cache.get(key, 0) if count 5: return False return True登录失败时给这个计数器加一成功时删掉计数器。这个方案不碰数据库零成本挡住大部分暴力脚本。第二个是身份校验细节。有些学校要求学生用学号作为登录名并且要对学号格式做校验。做法是自定义一个Django认证后端from django.contrib.auth.backends import ModelBackend from django.contrib.auth.models import User class StudentLoginBackend(ModelBackend): def authenticate(self, request, usernameNone, passwordNone, **kwargs): # 学号一般形如202301011234共12位 if not username or len(username) ! 12: return None user User.objects.filter(usernameusername).first() if user and user.check_password(password): return user return None权限控制方面学生只能看自己的选课记录教师只能管理自己开的课。Django自带的权限系统可以做但更直接的是写一个装饰器在视图层拦截from django.http import HttpResponseForbidden def role_required(allowed_roles): def decorator(view_func): def wrapper(request, *args, **kwargs): profile request.user.profile if profile.role not in allowed_roles: return HttpResponseForbidden(无权限访问) return view_func(request, *args, **kwargs) return wrapper return decorator3.2 并发选课抢课不超卖的核心逻辑这是整个系统最核心、最容易出错的地方。先看一个最直观但完全错误的写法# 错误示范先查余量再插入并发下必然超卖 course Course.objects.get(idcourse_id) if course.selected_count course.capacity: Enrollment.objects.create(studentstudent, coursecourse) course.selected_count 1 course.save()为什么错假设余量只剩1个学生A和学生B同时读到selected_count59而capacity60两人都判断还有空位于是都插入记录最终selected_count变成61超卖了一个名额。正确做法主要分三个层级。第一层是数据库事务加锁用SELECT ... FOR UPDATE把课程行锁住再判断余量from django.db import transaction transaction.atomic def select_course(request, course_id): student request.user # 锁住课程行其他事务必须等我提交才能读到最新值 course Course.objects.select_for_update().get(idcourse_id) if course.selected_count course.capacity: return error_response(课程已满) if Enrollment.objects.filter(studentstudent, coursecourse).exists(): return error_response(你已选过这门课) Enrollment.objects.create(studentstudent, coursecourse) course.selected_count 1 course.save() return success_response()这段代码有两个关键点。select_for_update()必须在事务内使用否则锁不会生效——这个坑我踩过transaction.atomic忘记加在最外层结果锁完全没起作用并发测试一跑就超卖。另外因为锁住了课程行同一门课的并发选课请求会排队执行不会出现同时判断余量的情况。第二层是唯一约束兜底。即便业务代码漏了检查UNIQUE(student_id, course_id)也能在数据库层拦截重复选课保证数据不会烂掉。第三层是Redis削峰。把选课请求先扔进Redis队列后台异步消费这种方式适合选课峰值极高、单机数据库扛不住的情况。但说实话如果数据库锁的方案设计得合理大部分学校场景都扛得住。Redis队列真正的价值还有另外一个选课成功或者失败之后可以推送一条站内通知给学生体验明显提升。3.3 退课与容量回收退课逻辑比选课简单但有个细节特别容易漏。退课必须同步回退课程表的selected_count否则会出现学生明明退课了名额却没有释放的问题。我见过有同学只删了选课记录忘了更新课程表的计数结果一个学期下来课程余量数据越差越多。退课函数如下from django.db.models import F transaction.atomic def drop_course(request, course_id): student request.user course Course.objects.select_for_update().get(idcourse_id) deleted, _ Enrollment.objects.filter( studentstudent, coursecourse ).delete() if deleted: course.selected_count F(selected_count) - 1 course.save(update_fields[selected_count])注意这里用F()表达式做原子自减而不是先读出selected_count再加一减一再写回。F()可以保证读到当前值、减一、写回这三步在数据库内部完成避免并发下互相覆盖。实际上退课场景并发量不大但养成用F()的习惯能少踩很多数据一致性的坑。3.4 选课时间窗口控制很多系统的选课开放时间是硬编码写在配置文件里。一旦学校调整时间就要改代码重新部署非常不便。更合理的做法是把时间窗口做进数据库管理员在后台点几下就能改。我在前面建表时加了一个app_select_window表选课接口里先判断当前时间是否落在窗口内from django.utils import timezone def check_window(request, window_name): now timezone.now() window SelectWindow.objects.filter( namewindow_name, is_activeTrue ).first() if not window: return error_response(选课批次不存在) if now window.start_time: return error_response(选课尚未开始) if now window.end_time: return error_response(选课已结束) return None这里有个性能小坑每次选课请求都查一次窗口表高峰期会给数据库增加额外压力。优化方式是把窗口配置缓存到Redis管理员改动窗口时主动失效对应缓存。这样数据库只在配置变更时才被访问一次选课高峰期直接读缓存。4. 课程管理与后台功能4.1 什么时候该做前后端分离现在的项目动不动就问前后端分离吗其实这是个伪命题。选课系统这个体量Django模板加Bootstrap就能把学生端和管理员端做得非常完整完全没有必要拆出Vue或React。拆分离意味着要同时维护两套代码接口文档、跨域处理、Token管理全都要跟上复杂度直线上升对内部系统来说收益却很小。我实际做的是Django模板渲染页面AJAX做局部刷新。比如选课页面学生点选课按钮前端发一个POST请求后端返回JSON前端根据结果更新按钮状态和余量显示。这个模式够用、好调试、维护成本低。如果将来真的要出小程序或者APP再给现有系统补一套REST API也不迟。Django有DRF把已有视图函数改造成APIView其实没那么难关键是核心业务逻辑要写得干净别把页面渲染代码和业务逻辑揉在一起。4.2 管理员后台的关键功能Django Admin开箱即用但默认界面对于选课系统来说还不够。需要扩展的地方主要有三块。第一是课程批量导入。每学期开学老师带着一堆课程表数据来录入手工一条条输入要人命。我做了CSV导入功能用文件上传加Python的csv模块解析批量创建课程记录。这里强烈建议先做模板下载功能让老师按模板填写再上传否则数据格式千奇百怪解析代码会写到崩溃。第二是选课结果导出。管理员要能随时导出某门课的选课名单用于成绩录入用Django的内存CSV导出最方便import csv from django.http import HttpResponse from urllib.parse import quote def export_enrollment(request, course_id): course Course.objects.get(idcourse_id) enrollments Enrollment.objects.filter(coursecourse).select_related(student) response HttpResponse(content_typetext/csv) filename quote(f{course.course_name}_选课名单.csv) response[Content-Disposition] fattachment; filename*UTF-8\\{filename} writer csv.writer(response) writer.writerow([学号, 姓名, 选课时间]) for e in enrollments: writer.writerow([e.student.username, e.student.first_name, e.enrolled_at]) return response中文文件名一定要做URL编码否则浏览器下载时会出现乱码文件名这个坑我在第一版就踩过。第三是数据看板。管理员最关心的是哪些课满了、哪些课没人选、各学院选课比例。我用Django ORM的聚合查询直接生成统计页面from django.db.models import Count popular_courses Course.objects.annotate( cntCount(enrollment) ).filter(cnt__gte50).order_by(-cnt)[:10] deserted_courses Course.objects.annotate( cntCount(enrollment) ).filter(cnt__lte5).order_by(cnt)选课结束两天后连续两轮都没人选满的课管理员就需要考虑是否停开、是否需要通知学生调整计划。4.3 课程状态机设计课程状态如果只用一个布尔字段开/关后面一定会遇到麻烦。未开放选课中已满已关闭这几种状态在业务上是不同的。我在代码里做了一组简单的状态判断def get_course_status(course, now): if course.selected_count course.capacity: return full window SelectWindow.objects.filter( namecourse.semester, is_activeTrue ).first() if window and now window.start_time: return not_open if window and now window.end_time: return closed return open这样做的好处是管理员不用每天手动开开关关系统在窗口开始后课程自动进入可选状态满了自动显示已满。前端根据状态决定按钮是选课、已满还是未开放交互逻辑清晰了不少。5. 性能优化与部署上线经验5.1 数据库性能调优选课系统的数据库压力集中在三处课程列表查询、选课写入、余量校验。我第一次压测时课程列表接口在500门课程、3000学生同时访问的情况下响应时间从200毫秒直接涨到2秒多。定位发现是N1查询问题课程列表页每显示一门课就单独查一次教师信息500门课产生了501条SQL。用Django的select_related解决courses Course.objects.select_related(teacher).filter( semester2025-01 )这个改动把SQL数量从501条降到了1条响应时间回到300毫秒以内。凡是涉及外键关联的查询一定要养成本能反应这段代码会不会触发N1用Django Debug Toolbar跑一遍页面SQL数量和耗时一目了然。数据库连接池也要留意。Django默认每个线程持有一个连接Gunicorn开8个worker再加上后台任务可能同时有十几个连接。如果PostgreSQL的max_connections设置太小高峰期会报too many connections。我在settings里配置了CONN_MAX_AGE60让连接保持60秒复用窗口明显减少了重复建连的开销。5.2 缓存策略Redis到底该缓存什么选课系统的热点数据比较明确我用Redis做了三层缓存。第一层是课程列表页缓存。课程列表短时间内不会变缓存30秒完全可行。我用Django自带的cache_page装饰器from django.views.decorators.cache import cache_page cache_page(30) def course_list(request): ...第二层是选课窗口配置这个数据变更频率低缓存30秒就够了。第三层是学生已选课程列表学生进我的课表页面要查选课记录加课程详情属于典型热查询缓存5分钟。注意一点选课、退课成功后必须主动删除该学生课表页的缓存key否则学生会看到过期数据。实践下来有个经验不要试图缓存一切只缓存读多写少且一致性要求不苛刻的数据。像课程余量这种数据选课期间每时每刻都在变缓存5秒都可能引发超卖反而不如不缓存——直接用数据库锁保护的事务逻辑更稳。5.3 Gunicorn、Supervisor与Nginx的组合部署部署方案是比较经典的三件套稳定到可以说有点无聊但极其可靠Nginx处理静态文件和反向代理Gunicorn跑Django应用Supervisor守护Gunicorn进程。Gunicorn的worker数量按CPU核数乘以2来配置不要盲目加大。worker太多会让数据库连接数翻倍、内存暴涨。我实测4核8G的机器8个worker的吞吐量反而比16个worker高原因是Python的多线程受GIL限制worker进程间的切换开销大于增加worker带来的收益。Supervisor配置大致这样写[program:course_system] command/home/deploy/venv/bin/gunicorn -w 8 -b 127.0.0.1:8000 course_project.wsgi:application directory/home/deploy/course_project autostarttrue autorestarttrue stderr_logfile/var/log/course_gunicorn.logNginx的关键配置是静态文件缓存和超时时间。静态文件用expires 7d能显著减少Django处理静态请求的压力。客户端超时不要设太短选课时偶尔有学生网速慢请求超过30秒就断连会造成选了但没选上的错觉。同时别忘了把Nginx的proxy_read_timeout调大一些保证反向代理不会提前掐断长请求。SSL证书用Lets Encrypt免费证书用certbot一键签发、自动续期。不要手动配置证书续期脚本我见过太多因为忘了续期导致网站打不开的事故。5.4 选课高峰期的容量演算选课开放前可以做一次快速容量估算。假设3000个学生、选课窗口10分钟、每个学生平均选2门课最坏情况下高峰期大概每秒需要处理10个选课请求单机数据库完全能扛住。但真正的瓶颈往往不是选课请求而是登录请求。更真实的场景是10分钟内3000人几乎同时点击登录登录接口的压力反而比选课接口大得多。所以登录页要做好限流同时把验证码校验放在登录接口的前置位置让脚本无法批量刷。再补一个经验选课前最好手动跑一次并发脚本做冒烟测试。我写过一个简单的Python测试脚本用线程池并发发送50个选课请求然后检查selected_count是否恰好等于成功数。跑完这个脚本大部分并发相关的bug都会暴露出来比上线后等学生投诉体面得多。6. 常见问题与排查技巧实录6.1 高频问题速查表现象可能原因排查方法选课超卖忘记加锁或锁没生效检查是否在事务内调用select_for_update用并发脚本复现学生重复选到一门课业务判断遗漏且唯一约束缺失确认UNIQUE(student_id, course_id)约束存在课程列表页特别慢N1查询或缺少索引用Django Debug Toolbar查SQL条数和耗时登录高峰卡死验证码接口无缓存无限制给登录接口加失败次数限制和速率限制下载名单中文名乱码Content-Disposition未做URL编码用quote()对文件名编码缓存数据一直不对缓存删除时机不对在事务提交后再删除对应缓存key显示选课成功但课表查不到缓存未同步或事务未提交检查缓存失效逻辑确认事务提交时机6.2 一个真实的缓存一致性bug我在第一版项目里遇到一个挺典型的问题。上线后学生反映明明显示选课成功刷新我的课表却看不到。排查发现选课事务确实提交了但课表页命中了旧缓存展示的是选课前的数据。问题根源在缓存一致性。选课、退课成功后我在同一个事务里删除了学生课表页的缓存key但缓存删除发生在事务提交之前——如果事务中途回滚缓存反而已经被删了下一个请求会从数据库读数据、重新写缓存写回去的仍是旧数据。这个时序问题很隐蔽。正确姿势是明确先提交事务再删缓存from django.core.cache import cache from django.db import transaction transaction.on_commit(lambda: cache.delete(fstudent_schedule_{student.id}))用transaction.on_commit注册回调函数事务成功提交后才会执行删除缓存的操作。此后类似场景我都用这个模式再没踩过同样的坑。6.3 部署上线后的几个隐藏问题选课系统上线后我遇到过几个文档里不会写明的坑。第一个是服务器时区。学校的选课时间按北京时间算如果服务器默认是UTC时间窗口整体偏移8小时。我在settings.py里显式设置TIME_ZONE Asia/Shanghai并且代码里统一用timezone.now()避免混用本地时间和UTC时间。第二个是数据库备份。选课数据直接关系到学生学分绝不能丢。我写了一个crontab脚本每天凌晨用pg_dump备份保留了最近7天的备份文件。第一次做完整流程演练时还挺顺利但后来发现备份文件里没有包含最新的表结构变更这个问题需要专门关注每次迁移数据库后都手动验证一次备份文件的可用性别等恢复时才后悔。第三个是监控告警。第一版部署后我基本靠学生打电话投诉发现问题这在实践中非常被动。后来加了一个简单的HTTP健康检查脚本每2分钟访问一次系统首页连续3次失败就发送告警邮件。别小看这个朴素的监控它帮我提前发现了两次因服务器内存不足导致的进程重启事故。7. 体验打磨与扩展方向7.1 从能用到好用的几个细节选课系统做完基础功能后建议花时间打磨几个体验细节这些东西不在需求文档里但对学生的使用感受影响很大。选课开始前要有倒计时页面避免学生无脑刷新选课成功要有即时反馈把课程名、上课时间、学分信息一起展示冲突检测要在选课前主动提示而不是等学生选完才发现时间撞了。冲突检测其实是个容易遗漏的功能。同一个学生选的课不能在同一时间上课否则期末考核没法安排。我实现了一个简单的检测函数拿新课程的上课时间段和已选课程逐个比对星期几和节次是否有交集有冲突就前端给警告并阻止提交。def check_time_conflict(student, new_course): enrolled_courses Course.objects.filter( enrollment__studentstudent, week_daynew_course.week_day, semesternew_course.semester ) for c in enrolled_courses: # 判断两个节次区间是否重叠 if new_course.start_section c.end_section and c.start_section new_course.end_section: return True return False这个检测逻辑用的区间重叠判断方式很简单但实测下来没有漏判过。7.2 功能扩展的优先级建议如果后续要继续演进这套系统我建议按这个优先级排第一做候补名单有人退课时系统自动把名额顺延给候补学生第二做通知模块和常见问题自动回复能大幅减少管理员高峰期的工作量第三做课程评价和历年选课数据统计辅助学生选课决策。这些功能都排在核心稳定之后再做不要一上来就铺开。选课系统最重要的评价标准永远是稳定其次是功能完整体验优化排最后。我在实际项目里还有一个体会选课系统的好不在于用了多新潮的技术而在于该稳的时候稳、该快的时候快、该提示的时候提示。把数据库事务、缓存一致性、窗口控制这些基础处理扎实了系统自然就好用了。最后再分享一个调试小技巧选课高峰期前手动写脚本模拟并发选课请求用线程池并发跑50个选课请求观察selected_count是否始终等于成功选课数。这个小测试几分钟就能跑完却能在上线前拦截掉大部分并发相关的问题值得沉淀成定时测试脚本每个学期开学前跑一遍。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

PHP跑分系统二开修复实战:三端架构、订单状态机与推广分账全解析 2026/10/2 21:56:49

PHP跑分系统二开修复实战:三端架构、订单状态机与推广分账全解析

简介:这套八月最新跑分二开修复版源码,面向代理、商户、用户三类角色协同使用的跑分平台,并内置完整推广系统,适合具备Linux与宝塔面板运维基础的技术人员部署使用。资源共2000个文件,约78.98MB,以PHP业务逻…

阅读更多 →
Python特产推荐系统毕设实战:从协同过滤到系统实现全解析 2026/10/2 21:56:47

Python特产推荐系统毕设实战:从协同过滤到系统实现全解析

每年三四月份,计算机专业的私聊窗口里有一类消息几乎年年准时出现:“学长,我的毕设题目是基于Python的特产推荐系统的设计与实现,拿到源码包和LW文档模板快两周了,还是不知道怎么开始写,能不能帮我理一下思…

阅读更多 →
SpringBoot+Vue律所案件管理系统:从架构到部署全解析 2026/10/2 21:56:46

SpringBoot+Vue律所案件管理系统:从架构到部署全解析

每年到了毕设季,一批又一批学生开始到处找“能直接跑起来的系统源码”。我后台私信被问得最多的,就是SpringBootVue系列的律师事务所案件管理系统。这套项目名字很长,但定位非常清晰:前端Vue,后端SpringBoot&#xff0…

阅读更多 →
PostgreSQL慢查询与阻塞排查实战:从锁到超时配置 2026/10/2 21:56:37

PostgreSQL慢查询与阻塞排查实战:从锁到超时配置

线上最刺激的事情,往往不是新功能上线,而是某个风和日丽的下午,系统突然开始卡顿。CPU占用飙到百分之九十多,业务接口普遍延迟三到五秒,监控群里一片哀嚎:数据库是不是出问题了?这时候如果你能在…

阅读更多 →
认知几何学:思维如何弯曲意义空间 2026/10/2 21:56:35

认知几何学:思维如何弯曲意义空间

你大概听过一个说法:质量告诉空间如何弯曲,空间又告诉质量如何运动。广义相对论的核心,其实就藏在这两句循环嵌套的话里。我把这套逻辑搬进了认知领域,改写成另一个版本:思维告诉意义空间如何弯曲,弯曲之后…

阅读更多 →
SqlSugar 5.x联表查询实战:类型安全、性能优化与踩坑实录 2026/10/2 21:56:31

SqlSugar 5.x联表查询实战:类型安全、性能优化与踩坑实录

做后端接口的老哥应该都遇到过这个需求:页面要展示一个订单列表,但订单表里只有UserId,界面上却要显示用户名,还得带上订单明细里的商品名称、数量。这不是查单表能搞定的,是典型的主表从表字典数据的组合查询场景。对…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉