tulip notes
首页
  • 学习笔记

    • 《Vue》
  • 踩坑日记

    • JavaScript
  • MQ
  • Nginx
  • IdentityServer
  • Redis
  • Linux
  • Java
  • SpringBoot
  • SpringCloud
  • MySql
  • docker
  • 算法与设计模式
  • 踩坑与提升
  • Git
  • GitHub技巧
  • Mac
  • 网络
  • 项目构建合集
  • 一些技巧
  • 面试
  • 一些杂货
  • 友情链接
  • 项目发布
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Star-Lord

希望一天成为大师的学徒
首页
  • 学习笔记

    • 《Vue》
  • 踩坑日记

    • JavaScript
  • MQ
  • Nginx
  • IdentityServer
  • Redis
  • Linux
  • Java
  • SpringBoot
  • SpringCloud
  • MySql
  • docker
  • 算法与设计模式
  • 踩坑与提升
  • Git
  • GitHub技巧
  • Mac
  • 网络
  • 项目构建合集
  • 一些技巧
  • 面试
  • 一些杂货
  • 友情链接
  • 项目发布
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 设计相关

  • 运行相关

  • 事务相关

  • 表设计实战系列

    • 表设计实战-自增、资金与字符
    • 表设计-时间类型选择
    • 非结构存储:用好 JSON 这张牌
    • 忘记范式与使用页压缩
    • 认识索引的魅力
    • 组合索引与索引出错
    • 【实战】表设计与优化A
    • 【实战】表查询提升
    • 【实战】积分跟优惠券的设计
      • 积分表设计
        • 设计要点及原因
        • 表设计(MySQL)
        • 积分账户表(points_account)
        • 积分明细表(points_detail)
        • 积分规则表(points_rule)
        • 积分等级表(points_level)
        • 积分冻结记录(points_frozen)
      • 优惠券设计
        • 设计要点及原因
        • 高扩展性表设计(MySQL)
        • 1. 优惠券模板表(coupon_template)
        • 2. 用户优惠券表(coupon)
        • 3.优惠券核销记录表(coupon_use_log)
        • 4. 优惠券领取限制表(coupon_acquire_limit)(可选)
  • 分库分表

  • 框架使用

  • 常用sql跟关键字

  • 安装与卸载相关

  • 《MySql》笔记
  • 表设计实战系列
EffectTang
2025-03-07
目录

【实战】积分跟优惠券的设计

# 积分跟优惠券的设计

# 积分表设计

得想想积分模块通常需要哪些功能。用户赚取积分、消费积分、积分明细记录,可能还有积分规则和等级制度之类的。所以,表结构应该覆盖这些方面。

首先,用户积分账户表,应该是每个用户有一个账户,记录当前积分和冻结积分。冻结积分可能是因为有未完成的订单,暂时不能使用。这里主键应该是用户ID,或者单独设置一个账户ID?用户ID作为主键的话,可能更方便查询,但如果有分表分库的需求,可能需要单独的账户ID。不过用户ID一般是唯一的,可能直接用用户ID作为主键就行。字段的话,包括总积分、可用积分、冻结积分、更新时间这些。需要确保并发操作时的数据一致性,所以可能需要乐观锁或者版本号字段。

然后是积分明细表,记录每一次积分的变动。这里需要明细类型,比如获得、消费、过期等。积分值可以是正数或负数,比如消费是负数。相关的业务类型和业务ID,比如订单ID,活动ID之类的,方便以后查询。状态字段可能用来标识这笔明细是否有效,比如可能有些积分被撤销的情况。另外,需要记录生效时间和过期时间,这样处理积分过期的时候可以筛选出需要过期的记录。索引的话,可能需要在用户ID和业务类型上建索引,加快查询速度。

接下来是积分规则表,不同的积分获取或消费规则,比如签到送多少积分,订单金额兑换比例,或者不同等级的用户积分倍率。规则类型字段区分是获取还是消费,适用等级可能关联用户等级表,生效时间和失效时间控制规则的启用状态。这里可能需要一个规则内容字段,存储JSON格式的配置,比如{"points": 10}或者{"exchange_rate": 0.1},这样扩展性更好,不需要频繁改表结构。

积分等级表的话,可能需要等级名称、所需积分下限、权益描述等。这样用户达到一定积分后可以升级,享受不同的权益。权益可能也是JSON存储,方便扩展。

然后是积分冻结明细表,比如用户下单使用积分,但订单未完成时,需要冻结这部分积分,防止重复使用。冻结和解冻的时候需要记录关联的业务ID,比如订单ID,以及状态,比如冻结中、已解冻、已扣减。这样在处理订单完成或取消时,可以相应地处理冻结的积分。

关于扩展性,可能需要考虑模块化设计,各表之间通过外键关联,但实际中可能为了分库分表不用外键约束。使用状态字段和类型字段来区分不同的业务场景,避免每增加一个业务就需要新增字段。JSON字段的运用可以存储动态的规则内容,减少表结构变更。

在事务处理方面,积分账户的增减和明细记录需要在一个事务里,保证数据一致性。比如用户消费积分时,先扣减可用积分,增加冻结积分,同时记录明细。这里需要考虑并发问题,比如多个操作同时修改同一个用户的积分账户,可能需要使用乐观锁机制,通过版本号来控制。

# 设计要点及原因

  1. 账户与明细分离
    • 为什么:避免高频更新导致锁表,保证账户汇总效率
    • 如何做:用 积分账户表 存实时总额,积分明细表 记录流水
  2. 业务关联可追溯
    • 为什么:需追踪积分来源(如订单ID、活动ID)
    • 如何做:添加 业务类型+业务ID 字段,支持多场景扩展
  3. 灵活规则配置
    • 为什么:不同活动/等级积分规则可能频繁变化
    • 如何做:用 JSON字段 存储动态规则,避免频繁改表
  4. 过期与冻结机制
    • 为什么:防止积分滥用,需支持预冻结和自动过期
    • 如何做:通过 状态字段 + 过期时间 + 定时任务实现
  5. 并发安全
    • 为什么:防止超额兑换
    • 如何做:通过 乐观锁(版本号)或 SELECT FOR UPDATE 控制

# 表设计(MySQL)

# 积分账户表(points_account)

CREATE TABLE points_account (
    user_id BIGINT UNSIGNED PRIMARY KEY COMMENT '用户ID',
    total_points INT NOT NULL DEFAULT 0 COMMENT '累计积分(含已过期)',
    available_points INT NOT NULL DEFAULT 0 COMMENT '可用积分',
    frozen_points INT NOT NULL DEFAULT 0 COMMENT '冻结积分',
    late_points int not null default 0 commit '要过期积分(30天内 或者按月份来)',
    version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号',
    update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) COMMENT '积分账户汇总';
1
2
3
4
5
6
7
8
9

索引:user_id 主键天然有索引

# 积分明细表(points_detail)

CREATE TABLE points_detail (
    id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    user_id BIGINT UNSIGNED NOT NULL COMMENT '用户ID',
    points INT NOT NULL COMMENT '变动积分(正负值)',
    type TINYINT NOT NULL COMMENT '类型:1-获取 2-消费 3-过期',
    biz_type VARCHAR(32) NOT NULL COMMENT '业务类型:sign/daily_login/order...',
    biz_id VARCHAR(64) NOT NULL COMMENT '业务ID(如订单ID)',
    status TINYINT NOT NULL DEFAULT 1 COMMENT '状态:1-有效 2-已撤销',
    description VARCHAR(255) COMMENT '描述',
    effect_time DATETIME NOT NULL COMMENT '生效时间',
    expire_time DATETIME COMMENT '过期时间(可为空)',
    create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
) COMMENT '积分明细流水';
1
2
3
4
5
6
7
8
9
10
11
12
13

索引:

  • idx_user_id_type (user_id, type) → 快速查用户某类积分
  • idx_biz (biz_type, biz_id) → 业务溯源

# 积分规则表(points_rule)

CREATE TABLE points_rule (
    id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    rule_type TINYINT NOT NULL COMMENT '规则类型:1-赚取 2-消费',
    name VARCHAR(64) NOT NULL COMMENT '规则名称',
    config JSON NOT NULL COMMENT '动态配置(如{"points":10, "daily_max":100})',
    min_level INT DEFAULT 0 COMMENT '适用最低等级',
    effect_start DATETIME NOT NULL,
    effect_end DATETIME NOT NULL,
    create_time DATETIME DEFAULT CURRENT_TIMESTAMP
) COMMENT '积分规则配置';
1
2
3
4
5
6
7
8
9
10

索引:idx_rule_type (rule_type) + 时间范围查询优化

# 积分等级表(points_level)

CREATE TABLE points_level (
    level INT UNSIGNED PRIMARY KEY COMMENT '等级',
    level_name VARCHAR(32) NOT NULL COMMENT '等级名称',
    min_points INT NOT NULL COMMENT '最低积分要求',
    rights JSON COMMENT '权益配置(如{"discount":0.9})'
) COMMENT '积分等级配置';
1
2
3
4
5
6

# 积分冻结记录(points_frozen)

CREATE TABLE points_frozen (
    freeze_id VARCHAR(64) PRIMARY KEY COMMENT '冻结ID(业务生成)',
    user_id BIGINT UNSIGNED NOT NULL,
    points INT NOT NULL COMMENT '冻结积分',
    biz_type VARCHAR(32) NOT NULL COMMENT '关联业务类型',
    biz_id VARCHAR(64) NOT NULL COMMENT '关联业务ID',
    status TINYINT NOT NULL DEFAULT 1 COMMENT '1-冻结中 2-已解冻 3-已扣减',
    create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) COMMENT '积分冻结记录';
1
2
3
4
5
6
7
8
9
10

# 优惠券设计

确定优惠券模块的核心需求。

优惠券通常包括

  • 创建、发放、使用、过期等流程。

  • 优惠券的基本信息(类型、面值、使用条件)、

  • 发放规则(用户领取、系统发放)、

  • 使用限制(商品、分类、时间)、

  • 状态管理(未使用、已使用、过期)以及核销记录。

此外,扩展性很重要,比如支持不同类型的优惠券(满减、折扣、礼品券),以及未来可能新增的使用条件。

在设计表时,需要注意以下几点:

  1. 优惠券信息与实例分离:优惠券模板和用户持有的优惠券实例分开存储,这样同一个模板可以生成多个实例,避免重复数据,同时方便管理状态。

  2. 灵活的使用条件:使用JSON字段存储条件,比如满减金额、适用商品分类等,避免频繁修改表结构。

  3. 使用限制与核销记录:记录优惠券的使用时间、订单ID等,便于核对和退款处理。同时需要处理并发使用的问题,防止重复使用。

  4. 状态管理与过期处理:优惠券可能有未使用、已使用、已过期等状态,需要定时任务检查过期时间并更新状态。

  5. 发放机制:支持用户领取和系统自动发放,可能需要记录领取次数限制和用户领取记录。

# 设计要点及原因

  1. 模板与实例分离
    • 为什么:同一优惠券模板可生成多个实例(如“新人礼包”发10万张券)
    • 如何做:coupon_template 存规则,coupon 存用户持有的具体券
  2. 动态使用规则
    • 为什么:不同券的适用商品、金额门槛等差异大
    • 如何做:用 JSON字段 存储规则(如 {"min_order_amount":100}),避免频繁改表
  3. 状态与过期管理
    • 为什么:需跟踪券是否已用、过期,且需定时任务自动失效
    • 如何做:status 字段标记状态,expire_time 控制过期,定时任务扫描更新
  4. 防超发与防超用
    • 为什么:避免库存超发或用户重复使用同一张券
    • 如何做:通过 数据库唯一约束 + 乐观锁 控制并发
  5. 核销溯源
    • 为什么:需记录券的使用时间、订单、操作人,便于退款或审计
    • 如何做:独立的 coupon_use_log 表记录核销流水

# 高扩展性表设计(MySQL)

# 1. 优惠券模板表(coupon_template)

CREATE TABLE coupon_template (
    id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY COMMENT '模板ID',
    name VARCHAR(64) NOT NULL COMMENT '券名称(如满100减20)',
    type TINYINT NOT NULL COMMENT '类型:1-满减 2-折扣 3-礼品券',
    rule_config JSON NOT NULL COMMENT '规则配置(如{"min_amount":100,"discount":20})',
    total_stock INT UNSIGNED NOT NULL COMMENT '总库存',
    remaining_stock INT UNSIGNED NOT NULL COMMENT '剩余库存',
    user_limit TINYINT UNSIGNED NOT NULL DEFAULT 1 COMMENT '每人限领数量',
    applicable_scope JSON COMMENT '适用范围(如{"category_ids":[1,2]})',
    validity_type TINYINT NOT NULL COMMENT '有效期类型:1-固定时间 2-领取后N天有效',
    start_time DATETIME COMMENT '有效期开始时间(类型1时需填)',
    end_time DATETIME COMMENT '有效期结束时间(类型1时需填)',
    valid_days INT UNSIGNED COMMENT '领取后有效天数(类型2时需填)',
    status TINYINT NOT NULL DEFAULT 1 COMMENT '状态:1-生效 2-停用',
    create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
) COMMENT '优惠券模板';
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

索引:

  • idx_status_type (status, type) → 快速筛选可用券模板
  • idx_validity (start_time, end_time) → 有效期查询优化

# 2. 用户优惠券表(coupon)

CREATE TABLE coupon (
    id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    user_id BIGINT UNSIGNED NOT NULL COMMENT '用户ID',
    template_id BIGINT UNSIGNED NOT NULL COMMENT '关联模板ID',
    code VARCHAR(32) NOT NULL COMMENT '券唯一码(加密)',
    status TINYINT NOT NULL DEFAULT 1 COMMENT '状态:1-未使用 2-已使用 3-已过期',
    obtain_time DATETIME NOT NULL COMMENT '领取时间',
    expire_time DATETIME NOT NULL COMMENT '过期时间',
    use_time DATETIME COMMENT '使用时间',
    order_id BIGINT UNSIGNED COMMENT '使用的订单ID',
    version INT UNSIGNED NOT NULL DEFAULT 0 COMMENT '乐观锁版本号',
    UNIQUE KEY uk_code (code),
    KEY idx_user_status (user_id, status)
) COMMENT '用户持有的优惠券';
1
2
3
4
5
6
7
8
9
10
11
12
13
14

索引:

  • uk_code 唯一索引 → 防券码重复
  • idx_user_status → 快速查用户可用券

# 3.优惠券核销记录表(coupon_use_log)

CREATE TABLE coupon_use_log (
    id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    coupon_id BIGINT UNSIGNED NOT NULL COMMENT '券ID',
    user_id BIGINT UNSIGNED NOT NULL,
    order_id BIGINT UNSIGNED NOT NULL COMMENT '订单ID',
    used_amount DECIMAL(10,2) NOT NULL COMMENT '抵扣金额',
    use_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '使用时间',
    operator_id BIGINT UNSIGNED COMMENT '操作人ID(系统/管理员)',
    refund_time DATETIME COMMENT '退款时间',
    KEY idx_coupon_order (coupon_id, order_id)
) COMMENT '券使用记录(支持退款溯源)';
1
2
3
4
5
6
7
8
9
10
11

# 4. 优惠券领取限制表(coupon_acquire_limit)(可选)

CREATE TABLE coupon_acquire_limit (
    user_id BIGINT UNSIGNED NOT NULL,
    template_id BIGINT UNSIGNED NOT NULL,
    acquire_count INT UNSIGNED NOT NULL DEFAULT 0 COMMENT '已领取次数',
    PRIMARY KEY (user_id, template_id)
) COMMENT '用户领取次数限制';
1
2
3
4
5
6

上次更新: 2025/04/23, 16:23:16
【实战】表查询提升
简介分库分表

← 【实战】表查询提升 简介分库分表→

最近更新
01
面向切面跟自定义注解的结合
05-22
02
时间跟其他数据的序列化
05-19
03
数据加密与安全
05-17
更多文章>
Theme by Vdoing | Copyright © 2023-2025 EffectTang
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式