第七部分:部署与运维:让系统稳定运行
7.1 Docker容器化部署
容器化是现代应用部署的标准方式。Docker将应用及其依赖打包成一个镜像,实现环境一致性和快速部署。
FROM openjdk:11-jre-slim
# 设置时区(重要:很多业务依赖时间)
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
WORKDIR /app
COPY target/seckill-core-1.0.0.jar app.jar
# 健康检查(K8s会定期调用)
HEALTHCHECK --interval=30s --timeout=3s \
CMD curl -f http://localhost:8080/actuator/health || exit 1
ENTRYPOINT ["java", "-jar", "app.jar"]
7.2 Docker Compose一键部署
version: '3.8'
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root123
MYSQL_DATABASE: seckill_db
volumes:
- mysql_data:/var/lib/mysql # 数据持久化
redis:
image: redis:7-alpine
command: redis-server --appendonly yes # 开启持久化
rabbitmq:
image: rabbitmq:3-management-alpine
ports:
- "15672:15672" # 管理界面
seckill-app:
build: .
depends_on:
- mysql
- redis
- rabbitmq
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/seckill_db
SPRING_REDIS_HOST: redis
SPRING_RABBITMQ_HOST: rabbitmq
7.3 监控告警:及时发现问题
核心监控指标:
业务指标:QPS、成功率、响应时间
系统指标:CPU、内存、磁盘、网络
JVM指标:GC次数、GC时间、堆内存使用
# prometheus.yml
scrape_configs:
- job_name: 'seckill-app'
scrape_interval: 5s
metrics_path: '/actuator/prometheus'
static_configs:
- targets: ['seckill-app:8080']
关键告警规则:
groups:
- name: seckill-alerts
rules:
# 高错误率告警
- alert: HighErrorRate
expr: rate(http_server_requests_seconds_count{status=~"5.."}[1m]) > 0.1
annotations:
summary: "错误率超过10%"
# 响应时间告警
- alert: SlowResponse
expr: histogram_quantile(0.99, rate(http_server_requests_seconds_bucket[1m])) > 1
annotations:
summary: "P99响应时间超过1秒"
# 内存告警
- alert: HighMemoryUsage
expr: jvm_memory_used_bytes{area="heap"} / jvm_memory_max_bytes > 0.85
annotations:
summary: "堆内存使用率超过85%"
第八部分:总结与思考
8.1 秒杀系统的核心思想
回顾整个秒杀系统的设计,有几个核心思想值得反复品味:
流量控制:限流、削峰、异步处理,本质上是让系统在可控范围内处理请求
缓存为王:尽可能用内存代替磁盘,用空间换时间
最终一致性:不强求实时一致,通过异步和补偿达到最终一致
简单就是美:过度设计是万恶之源,合适的方案比完美的方案更重要
监控驱动优化:没有数据支撑的优化都是耍流氓
8.2 面试常见问题
Q1:如何防止超卖?
A:使用Redis DECR原子扣减,数据库乐观锁保证最终一致性。
Q2:如何防止重复秒杀?
A:使用Redis Set存储已秒杀用户,数据库唯一索引兜底。
Q3:秒杀系统如何保证高可用?
A:集群部署、熔断降级、限流保护、故障转移。
Q4:Redis库存和数据库库存不一致怎么办?
A:Redis作为预扣减,最终以数据库为准。可以定时对账修复。
Q5:如何应对恶意刷单?
A:IP限流、用户限流、验证码、行为分析、黑名单。
8.3 架构演进思考
从单体应用到微服务架构的演进,每一步都要权衡利弊:
什么时候需要引入Redis? 当数据库成为瓶颈时
什么时候需要引入MQ? 当同步处理响应时间过长时
什么时候需要拆分微服务? 当团队规模扩大、业务复杂度增加时
什么时候需要引入分布式事务? 当数据一致性要求极高时
记住:不要为了用技术而用技术,技术是解决问题的工具。
来源:
http://qcycj.cn/category/jiujieshao.html