Backend Development 20 min read

Design and Implementation of a Coupon System for a Rental Platform

This article details the end‑to‑end design of a coupon system for a rental listing platform, covering business flow, database schema, state management, caching strategies, distributed locking, and optimization techniques using design patterns, Redis, MySQL, and message queues.

Top Architect
Top Architect
Top Architect
Design and Implementation of a Coupon System for a Rental Platform

The platform provides rental listings for merchants and needs a coupon system to promote properties during holidays. The system consists of activities, coupons, and bindings between houses and coupons.

Business Flow : Merchants create activities, generate coupons, bind them to houses, and users claim coupons on the C‑side to receive discounts during checkout.

Technical Design :

1. Activity Table (t_activity) stores activity metadata such as time windows, city scope, coupon type, and status. Example schema:

CREATE TABLE `t_activity` (
  `activeId` bigint(20) NOT NULL COMMENT '活动ID',
  `title` varchar(256) NOT NULL COMMENT '活动名称',
  `applyStartTime` timestamp NULL DEFAULT NULL COMMENT '报名开始时间',
  `applyEndTime` timestamp NULL DEFAULT NULL COMMENT '报名停止时间',
  `activityStartTime` timestamp NULL DEFAULT NULL COMMENT '活动开始时间',
  `activityEndTime` timestamp NULL DEFAULT NULL COMMENT '活动结束时间',
  `cityIds` varchar(256) NOT NULL COMMENT '覆盖城市,多个逗号分隔',
  `couponType` tinyint(4) NOT NULL DEFAULT '0' COMMENT '优惠类型,1 直减;2 折扣;3免费住N天;4免押金;5特价房',
  `lowerLimit` int NOT NULL DEFAULT 0 COMMENT '优惠数值下限',
  `upperLimit` int NOT NULL DEFAULT 0 COMMENT '优惠数值上限',
  `description` text COMMENT '活动描述',
  `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '活动状态',
  `createTime` timestamp NULL DEFAULT NULL COMMENT '创建时间',
  `updateTime` timestamp NULL DEFAULT NULL COMMENT '更新时间',
  PRIMARY KEY (`activeId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='活动信息表';

2. Coupon Metadata Table (t_couponmeta) holds coupon definitions, including type, discount values, usage thresholds, and lifecycle timestamps.

CREATE TABLE `t_couponmeta` (
  `couponMetaId` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '券id',
  `appId` int(11) NOT NULL DEFAULT '1' COMMENT '区分建立来源',
  `activeId` bigint(20) NOT NULL DEFAULT '0' COMMENT '活动ID',
  `companyId` bigint(20) NOT NULL COMMENT '公司编号',
  `cityId` int(11) NOT NULL COMMENT '城市id',
  `title` varchar(256) NOT NULL COMMENT '优惠券名称',
  `couponType` tinyint(4) NOT NULL COMMENT '优惠券类型',
  `directDiscount` int(11) NOT NULL DEFAULT '0' COMMENT '直减券优惠力度',
  `discount` int(11) NOT NULL DEFAULT '0' COMMENT '折扣力度',
  `totalAmount` int(11) NOT NULL DEFAULT '0' COMMENT '券总数',
  `applyAmount` int(11) NOT NULL DEFAULT '0' COMMENT '已领取总数',
  `status` int(11) NOT NULL DEFAULT '10' COMMENT '10:新建未启用,20:已启用,30:过期, 40 已结束 50 已中止',
  `expireType` tinyint(4) NOT NULL DEFAULT '1' COMMENT '类型:1固定有效期,2浮动有效期',
  `recordStatus` tinyint(4) DEFAULT '0' COMMENT '数据状态',
  PRIMARY KEY (`couponMetaId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='优惠券表';

3. Binding Table (t_bindcoupon) records which house is bound to which coupon and its current binding status, with a distributed lock to prevent over‑binding.

CREATE TABLE `t_bindcoupon` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `couponMetaId` int(11) NOT NULL COMMENT '券id',
  `companyId` bigint(20) NOT NULL COMMENT '公司编号',
  `activityStatus` tinyint(4) NOT NULL COMMENT '状态 0 准备中 1 活动中 2 活动结束 券未失效 3 活动结束券失效',
  `houseId` bigint(20) NOT NULL DEFAULT '0' COMMENT '房源id',
  `recordStatus` tinyint(4) NOT NULL COMMENT '数据状态 0 有效,-1 失效',
  `createTime` timestamp NULL DEFAULT NULL COMMENT '创建时间',
  `updateTime` timestamp NULL DEFAULT NULL COMMENT '更新时间',
  PRIMARY KEY (`id`),
  KEY `idx_companyId_couponMetaId` (`companyId`,`couponMetaId`)
) ENGINE=InnoDB AUTO_INCREMENT=17379 DEFAULT CHARSET=utf8 COMMENT='优惠券绑定范围表';

Design Patterns : The service uses the Proxy pattern for read‑heavy operations, caching activity and coupon data in Redis; the State pattern drives activity and coupon lifecycle; the Observer pattern notifies downstream services via MQ when state changes.

Coupon Claim Process involves three steps: request validation (including Bloom filter checks), atomic stock decrement in Redis, and a transactional MySQL record insertion via a DB message queue. The system handles normal and abnormal cases such as Redis failure, DB crash, and master‑slave inconsistency.

Optimization Directions include sharding coupon data, scaling Redis clusters, pod‑level request routing, hot‑key local caches, and binlog‑based cache synchronization (Canal).

In summary, the coupon system combines multi‑level caching, asynchronous message‑driven updates, and robust state management to achieve high concurrency, data consistency, and operational simplicity.

Design Patternsbackend architectureMicroservicesRediscachingMySQLcoupon system
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.