智速优座项目总结

目录

一、做这个项目的背景

二、技术栈的选择

前端技术栈

后端技术栈

项目架构图

三、核心功能的详解

[1. 用户系统:登录注册与权限控制](#1. 用户系统:登录注册与权限控制)

[2. 演出搜索:让用户快速找到想看的演出](#2. 演出搜索:让用户快速找到想看的演出)

[3. 智能推荐:猜你喜欢](#3. 智能推荐:猜你喜欢)

数据来源

推荐策略

[4. 核心交互:选座购票](#4. 核心交互:选座购票)

[4.1 交互式座位图](#4.1 交互式座位图)

[4.2 座位锁定机制](#4.2 座位锁定机制)

[5. 秒杀系统:高并发挑战](#5. 秒杀系统:高并发挑战)

[6. 订单管理:全生命周期追踪](#6. 订单管理:全生命周期追踪)

[7. 智能客服:24小时在线答疑](#7. 智能客服:24小时在线答疑)

[7.1 多轮对话支持](#7.1 多轮对话支持)

[7.2 知识库集成](#7.2 知识库集成)

[7.3 智能路由](#7.3 智能路由)

[7.4 客服界面](#7.4 客服界面)

[8. 后台管理系统](#8. 后台管理系统)

[8.1 演出管理](#8.1 演出管理)

[8.2 用户管理](#8.2 用户管理)

[8.3 订单管理](#8.3 订单管理)

[8.4 数据统计](#8.4 数据统计)

四、项目中遇到的问题以及解决

问题一:库存超卖

问题二:缓存一致性问题

问题三:分布式事务问题

问题四:消息队列堆积

五、项目的亮点

六、项目总结与感受


这篇博客是我做完这个项目后的一个总结

一、做这个项目的背景

这是一个高并发的票务平台项目;

做这个项目的初衷是:市面上的票务平台,对于个别城市开放的中小型演出没有兼顾到,并且在热门演出开票时常常出现卡顿,库存超卖的情况,我想切实的解决这些问题,所以做了这个项目试水
核心目标有三个:

  1. 扛住高并发:秒杀场景下能稳定处理大量请求
  2. 数据实时同步:座位、订单状态要实时更新
  3. 智能化体验:给用户推荐感兴趣的演出,用AI客服减轻运营压力

二、技术栈的选择

前端技术栈

  • 框架:Vue 3 + TypeScript(Vue3的组合式API太好用了,TypeScript让代码更规范)
  • 构建工具:Vite(开发体验好)
  • 状态管理:Pinia(Vue官方推荐)
  • 路由:Vue Router 4(单页应用必备)
  • UI组件库:Element Plus(组件丰富,文档友好)
  • 样式:Tailwind CSS 3(原子化CSS,写样式快到飞起)

后端技术栈

  • 框架:FastAPI(Python异步生态成熟,开发效率高,自动生成API文档)
  • 数据库:MySQL 8.0 + SQLAlchemy 2.0(关系型数据库首选,ORM用着省心)
  • 缓存:Redis 7(支持分布式锁、原子操作,秒杀必备)
  • 搜索:Elasticsearch 8(全文检索性能好,还支持向量检索)
  • 消息队列:RabbitMQ(异步任务处理,解耦业务)
  • AI能力:Dify(可视化工作流,快速集成LLM)

项目架构图

复制代码
┌─────────────────────────────────────────────────────────────┐
│                     前端层 (Vue3 + TypeScript)              │
├─────────────────────────────────────────────────────────────┤
│              API Gateway (FastAPI + Nginx)                  │
├─────────────────────────────────────────────────────────────┤
│  ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌──────────────────┐   │
│  │  用户服务│ │ 演出服务│ │ 订单服务 │ │     AI服务       │   │
│  │         │ │         │ │         │ │ (Dify工作流)     │   │
│  └────┬────┘ └────┬────┘ └────┬────┘ └────────┬─────────┘   │
│       │           │           │                │            │
├───────┼───────────┼───────────┼────────────────┼───────────┤
│       ▼           ▼           ▼                ▼            │
│  ┌─────────────────────────────────────────────────────────┐│
│  │                      中间件层                            ││
│  │  Redis(座位锁/热点缓存)  │  RabbitMQ(异步消息任务)        ││
│  │  Elasticsearch(演出检索) │  Canal(MySQL数据同步)         ││
│  └─────────────────────────────────────────────────────────┘│
├─────────────────────────────────────────────────────────────┤
│                   数据持久层 (MySQL 8.0)                     │
└─────────────────────────────────────────────────────────────┘

三、核心功能的详解

1. 用户系统:登录注册与权限控制

用户模块是基础,我们做了手机号注册、密码登录,还集成了JWT认证

登录成功后返回token,后续请求都要带上这个token

python 复制代码
@app.post("/api/login")
async def login(username: str, password: str):
    user = await get_user_by_username(username)
    if not user or not verify_password(password, user.password):
        raise HTTPException(status_code=401, detail="用户名或密码错误")
    
    access_token = create_access_token(data={"sub": user.username})
    return {"access_token": access_token, "token_type": "bearer"}

2. 演出搜索:让用户快速找到想看的演出

搜索功能用了Elasticsearch,支持关键词搜索、分类筛选、城市筛选

比如用户搜"周杰伦",就能找到相关演出

python 复制代码
async def search_performance(keyword: str, city: str = None):
    query = {"bool": {"must": [{"match": {"name": keyword}}], "filter": []}}
    if city:
        query["bool"]["filter"].append({"term": {"city": city}})
    
    result = await es_client.search(index="performance_index", query=query)
    return [hit["_source"] for hit in result["hits"]["hits"]]

3. 智能推荐:猜你喜欢

这个功能是提升用户转化率的关键,我们基于用户行为做个性化推荐:

数据来源

  • 用户浏览过的演出
  • 用户购买过的演出
  • 用户搜索过的关键词
  • 用户收藏的演出

推荐策略

  • 协同过滤:根据相似用户的行为推荐
  • 内容推荐:根据演出类型、艺人、城市推荐
  • 热门推荐:结合平台热度综合推荐
    实现方式: 我们用Dify搭建了推荐工作流,输入用户行为数据,输出个性化推荐列表
python 复制代码
async def get_personalized_recommend(user_id: int):
    # 获取用户最近30天的行为数据
    behavior = await get_user_behavior(user_id)
    
    # 调用Dify工作流生成推荐
    response = await dify_client.run_workflow(
        workflow_id="personalized_recommend",
        inputs={
            "user_id": user_id,
            "behavior": behavior,
            "top_k": 6  # 返回6个推荐结果
        }
    )
    
    return response.get("recommendations", [])

效果: 上线后,推荐模块的点击率比随机推荐提升了35%,用户转化率提升了20%

4. 核心交互:选座购票

这部分是用户购票的核心流程,我们做了很多优化:

4.1 交互式座位图

用户进入选座页面后,会看到一个可视化的座位图,不同状态的座位用不同颜色区分:

  • 绿色:可选座位
  • 红色:已售出座位
  • 蓝色:用户已选座位
  • 黄色:临时锁定座位
python 复制代码
<template>
  <div class="seat-map-container">
    <div class="stage-indicator">舞台</div>
    <div class="seat-area">
      <div v-for="(row, rowIndex) in seatRows" :key="rowIndex" class="seat-row">
        <div class="row-label">{{ rowIndex + 1 }}</div>
        <div 
          v-for="seat in row" 
          :key="seat.id"
          :class="getSeatClass(seat)"
          @click="handleSeatClick(seat)"
        >
          <span v-if="seat.status === 0 && selectedSeats.includes(seat.id)">✓</span>
        </div>
      </div>
    </div>
  </div>
</template>

4.2 座位锁定机制

用户选好座位后,系统会自动锁定这些座位15分钟,防止被其他用户抢走:

python 复制代码
async def lock_seats(seat_ids: list, user_id: int) -> bool:
    async with async_session() as session:
        seats = await session.execute(
            select(Seat).where(Seat.id.in_(seat_ids), Seat.status == 0)
        )
        
        if len(seats.scalars().all()) != len(seat_ids):
            return False
        
        await session.execute(
            update(Seat)
            .where(Seat.id.in_(seat_ids))
            .values(status=2, lock_user_id=user_id, lock_time=datetime.now())
        )
        await session.commit()
        
        for seat_id in seat_ids:
            await redis_client.set(f"seat_lock:{seat_id}", user_id, ex=900)
        
        return True

5. 秒杀系统:高并发挑战

秒杀是最考验技术的部分。我们用Redis预减库存,再用MySQL乐观锁兜底,确保不会超卖。单SKU能支持5万次/秒的请求

python 复制代码
async def seckill(sku_id: int, user_id: int):
    result = await redis_client.decr(f"stock:{sku_id}")
    if result < 0:
        return False
    
    async with async_session() as session:
        update_count = await session.execute(
            update(PerformanceSKU)
            .where(PerformanceSKU.id == sku_id, PerformanceSKU.stock >= 1)
            .values(stock=PerformanceSKU.stock - 1)
        )
        
        if update_count.rowcount == 0:
            await redis_client.incr(f"stock:{sku_id}")
            return False
        
        await session.commit()
    return True

6. 订单管理:全生命周期追踪

订单状态流转很复杂,我们做了清晰的状态机:待支付→已支付→已出票,支持退票和取消。超时未支付的订单会自动取消

python 复制代码
待支付 → 已支付 → 已出票
    ↓         ↓
 支付失败    退票申请中 → 已退款
    ↓
 超时取消/主动取消

7. 智能客服:24小时在线答疑

7.1 多轮对话支持

用户可以和客服进行多轮对话,客服会记住上下文:

python 复制代码
async def ai_chat(user_id: int, question: str, session_id: str = None):
    history = await get_chat_history(user_id, session_id)
    messages = []
    for msg in history:
        messages.append({"role": msg.role, "content": msg.content})
    messages.append({"role": "user", "content": question})
    
    response = await dify_client.run_workflow(
        workflow_id="ai_chat",
        inputs={"user_id": user_id, "messages": messages}
    )
    
    await save_chat_history(user_id, response.get("session_id"), [
        {"role": "user", "content": question},
        {"role": "assistant", "content": response.get("answer")}
    ])
    
    return {"answer": response.get("answer"), "session_id": response.get("session_id")}

7.2 知识库集成

我们把演出信息、购票规则、退票政策等内容整理成知识库,让AI客服能准确回答用户问题

python 复制代码
async def query_knowledge_base(question: str) -> str:
    """查询知识库"""
    # 构建ES查询
    query = {
        "bool": {
            "should": [
                {"match": {"title": {"query": question, "boost": 2}}},
                {"match": {"content": question}}
            ]
        }
    }
    
    result = await es_client.search(index="knowledge_base", query=query)
    
    if result["hits"]["total"]["value"] > 0:
        return result["hits"]["hits"][0]["_source"]["content"]
    
    return None

7.3 智能路由

根据用户问题类型,自动路由到不同的处理逻辑:订单查询、退票政策、演出信息等

python 复制代码
async def process_user_question(user_id: int, question: str):
    """处理用户问题"""
    # 意图识别
    intent = await classify_intent(question)
    
    if intent == "order_status":
        # 查询订单状态
        order_no = extract_order_no(question)
        return await get_order_status(order_no)
    
    elif intent == "refund_policy":
        # 返回退票政策
        return await query_knowledge_base("退票政策")
    
    elif intent == "performance_info":
        # 查询演出信息
        performance_name = extract_performance_name(question)
        return await get_performance_info(performance_name)
    
    else:
        # 交给AI处理
        return await ai_chat(user_id, question)

7.4 客服界面

前端做了一个类似聊天软件的界面:

python 复制代码
<template>
  <div class="chat-container">
    <!-- 聊天消息列表 -->
    <div class="message-list">
      <div 
        v-for="(msg, index) in messages" 
        :key="index"
        :class="['message', msg.role]"
      >
        <div class="avatar">{{ msg.role === 'user' ? '我' : '客服' }}</div>
        <div class="content">{{ msg.content }}</div>
      </div>
    </div>
    
    <!-- 输入框 -->
    <div class="input-area">
      <input 
        v-model="inputMessage" 
        @keyup.enter="sendMessage"
        placeholder="请问有什么可以帮您?"
      />
      <button @click="sendMessage">发送</button>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const messages = ref<{role: string; content: string}[]>([
  {role: 'assistant', content: '您好!我是智速优座的智能客服,请问有什么可以帮您?'}
])
const inputMessage = ref('')

const sendMessage = async () => {
  if (!inputMessage.value.trim()) return
  
  // 添加用户消息
  messages.value.push({role: 'user', content: inputMessage.value})
  
  // 调用API
  const response = await api.aiChat(inputMessage.value)
  
  // 添加客服回复
  messages.value.push({role: 'assistant', content: response.answer})
  
  inputMessage.value = ''
}
</script>

8. 后台管理系统

有很多功能,这里挑重要的说

8.1 演出管理

  • 演出列表:支持分页、搜索、筛选(按状态、城市、类型)
  • 新增演出:填写演出名称、类型、海报、场馆、时间等信息
  • 场次管理:给演出添加多个场次,设置票价和库存
  • 座位管理:批量导入座位信息,可视化座位图编辑
  • 状态控制:一键上架/下架演出,自动下架过期演出

8.2 用户管理

  • 用户列表:查看所有用户,支持搜索和筛选
  • 用户详情:查看用户的基本信息、订单记录、积分余额
  • 黑名单管理:将恶意用户加入黑名单,禁止登录

8.3 订单管理

  • 订单列表:支持按订单号、用户ID、状态筛选
  • 订单详情:查看订单完整信息(座位、金额、支付方式等)
  • 退票审核:处理用户的退票申请,支持通过/拒绝
  • 订单统计:实时统计订单数量、销售额、转化率
python 复制代码
# 退票审核接口
@app.post("/api/admin/order/{order_id}/refund")
async def approve_refund(order_id: int, approved: bool, operator_id: int):
    async with async_session() as session:
        order = await session.get(Order, order_id)
        if not order or order.status != OrderStatus.REFUND_PENDING.value:
            raise HTTPException(status_code=400, detail="订单状态不允许")
        
        if approved:
            # 计算退款金额(扣除手续费)
            refund_amount = order.amount * (1 - (order.refund_fee_rate or 0))
            order.status = OrderStatus.REFUNDED.value
            order.refund_amount = refund_amount
            order.refund_approved = True
            order.refund_approve_time = datetime.now()
            order.refund_operator = operator_id
            
            # 返还库存
            await session.execute(
                update(PerformanceSKU)
                .where(PerformanceSKU.id == order.sku_id)
                .values(stock=PerformanceSKU.stock + 1)
            )
        else:
            order.status = OrderStatus.PAID.value
            order.refund_approved = False
        
        await session.commit()
    return {"message": "审核成功"}

8.4 数据统计

  • 销售统计:每日/每周/每月的订单数量、销售额、客单价
  • 演出排行:按销售额、购票人数排序的演出TOP10
  • 实时监控:当前在线用户数、系统响应时间、错误率
python 复制代码
# 获取销售统计数据
async def get_sales_statistics(start_date: date, end_date: date):
    async with async_session() as session:
        result = await session.execute(
            select(
                func.date(Order.create_time).label("date"),
                func.count(Order.id).label("order_count"),
                func.sum(Order.amount).label("total_amount")
            )
            .where(
                Order.create_time >= start_date,
                Order.create_time <= end_date,
                Order.status == OrderStatus.PAID.value
            )
            .group_by(func.date(Order.create_time))
        )
        
        return [{"date": row.date, "order_count": row.order_count, "total_amount": row.total_amount} 
                for row in result]

四、项目中遇到的问题以及解决

问题一:库存超卖

问题场景:第一次做秒杀测试的时候,我们准备了100张票,结果系统显示卖出去了120多张

问题表现

  • 秒杀开始后,库存瞬间变成负数
  • 用户下单成功但实际没有票
  • 客服收到大量投诉

根本原因: 我们一开始用的是"先查后改"的逻辑:在高并发场景下,多个请求同时查到库存>0,然后同时扣减,就导致了超卖

解决方案: 改成了"Redis预减库存 + MySQL乐观锁"的方案:

  1. 先用Redis的原子操作预减库存
  2. 再用MySQL乐观锁兜底
  3. 如果MySQL扣减失败,回滚Redis库存

效果:秒杀成功率达到99.99%,再也没出现过超卖问题

问题二:缓存一致性问题

问题场景:运营人员在后台修改了演出信息,但用户看到的还是旧数据

问题表现

  • 后台修改了演出票价,用户看到的还是旧价格
  • 演出下架了,但搜索结果里还能找到

根本原因: MySQL数据更新后,Redis缓存没有及时失效。我们一开始是手动删除缓存,但有时候会忘记,或者删除失败

解决方案

  1. 用Canal监听MySQL的binlog
  2. 当数据变化时,自动删除对应的Redis缓存
  3. 加一个缓存失效队列,确保缓存一定会被删除

效果:数据延迟从原来的几分钟降到了<100ms

问题三:分布式事务问题

问题场景:用户下单时,订单创建成功了,但座位锁定失败,导致数据不一致。

问题表现

  • 用户收到订单成功的消息,但选的座位还是可选状态
  • 同一个座位被多个用户下单

根本原因: 订单创建和座位锁定是两个独立的数据库操作,没有用事务管理。如果中间某个步骤失败,就会导致数据不一致。

解决方案: 用消息队列实现最终一致性:

  1. 先创建订单(状态为"待确认")
  2. 发送座位锁定消息到RabbitMQ
  3. 消费者收到消息后锁定座位
  4. 如果锁定成功,更新订单状态为"待支付"
  5. 如果锁定失败,取消订单

效果:订单和座位状态保持一致,再也没有出现过数据不一致的情况

问题四:消息队列堆积

问题场景:秒杀活动结束后,支付回调消息堆了好几万条,消费者处理不过来。

问题表现

  • RabbitMQ消息队列长度持续增长
  • 用户支付成功后,订单状态迟迟不更新
  • 系统响应变慢

根本原因: 我们一开始只部署了1个消费者,处理能力有限。秒杀时每秒产生几千条消息,远远超过了消费者的处理能力。

解决方案

  1. 动态扩容消费者数量(从1个增加到10个)
  2. 给消息设置优先级,重要消息优先处理
  3. 优化消费者代码,提高处理速度

效果:消息堆积问题得到缓解,消息处理延迟从原来的几分钟降到了几秒钟

五、项目的亮点

  1. 高并发秒杀:成功率99.99%
  2. 实时数据同步:Canal监听MySQL,数据延迟<100ms
  3. AI智能推荐:提升用户转化率20%
  4. 完善的选座体验:可视化座位图,智能锁定
  5. 智能客服:多轮对话,知识库支持
  6. 强大的后台管理:全流程运营支持
  7. Docker容器化:一键部署

六、项目总结与感受

做这个项目最大的收获,就是对"高并发"有了真正的理解。以前只在书本上看过的概念,这次都在实战中用到了

智能推荐、选座体验、智能客服这些功能虽然不是核心交易流程,但对提升用户体验和转化率至关重要。后台管理系统则是运营团队的核心工具,能大大提升工作效率
还有一个感悟:没有完美的系统,只有不断进化的系统。我

标签建议

通用标签

  • 文章分析
  • 内容标签
  • 关键词提取
  • 文本分类

技术/方法论标签

  • 自然语言处理
  • 文本挖掘
  • 信息检索
  • 机器学习

应用场景标签

  • 内容推荐
  • 知识管理
  • 数据标注
  • 智能摘要

细分领域标签

  • 语义分析
  • 主题建模
  • 特征提取
  • 标签生成

如果需要更具体的标签,可以提供文章内容或主题方向以便进一步细化。

现在的系统还有很多不足,但只要持续改进,就会越来越好

最后,如果你也在做类似的项目,欢迎一起交流!