1. 系统概述
分销系统是一种基于社交关系的电商营销模式,通过多级分销网络实现商品推广和销售。本文将详细介绍分销系统的技术架构、数据库设计和分佣规则实现。
2. 系统架构设计2.1 整体架构代码语言:javascript复制┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ 客户端层 │ │ API网关 │ │ 业务服务层 │
│ - Web前端 │───▶│ - 路由转发 │───▶│ - 用户服务 │
│ - 移动APP │ │ - 认证鉴权 │ │ - 商品服务 │
│ - 小程序 │ │ - 限流熔断 │ │ - 订单服务 │
└─────────────────┘ └──────────────────┘ └─────────────────┘
│
▼
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ 数据存储层 │◀──│ 数据访问层 │◀──│ 分销服务层 │
│ - MySQL │ │ - MyBatis │ │ - 关系管理 │
│ - Redis │ │ - JPA │ │ - 分佣计算 │
│ - Elasticsearch │ │ - Redis Template │ │ - 结算服务 │
└─────────────────┘ └──────────────────┘ └─────────────────┘2.2 核心服务模块代码语言:javascript复制// 分销系统核心服务类图
public class DistributionSystem {
// 用户服务
UserService userService;
// 分销关系服务
DistributionRelationService relationService;
// 分佣服务
CommissionService commissionService;
// 结算服务
SettlementService settlementService;
// 规则引擎
RuleEngine ruleEngine;
}3. 数据库设计3.1 核心表结构用户表 (users)代码语言:javascript复制CREATE TABLE users (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(100) NOT NULL UNIQUE,
email VARCHAR(255),
phone VARCHAR(20),
user_type TINYINT NOT NULL COMMENT '1-普通用户 2-分销员',
invite_code VARCHAR(20) NOT NULL UNIQUE COMMENT '邀请码',
parent_id BIGINT COMMENT '上级用户ID',
distribution_level INT DEFAULT 0 COMMENT '分销层级',
status TINYINT DEFAULT 1 COMMENT '状态',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_parent_id (parent_id),
INDEX idx_invite_code (invite_code)
);分销关系表 (distribution_relations)代码语言:javascript复制CREATE TABLE distribution_relations (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
user_id BIGINT NOT NULL,
ancestor_id BIGINT NOT NULL COMMENT '祖先节点ID',
level INT NOT NULL COMMENT '关系层级',
commission_rate DECIMAL(5,4) COMMENT '该层级分佣比例',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY uk_user_ancestor (user_id, ancestor_id),
INDEX idx_user_id (user_id),
INDEX idx_ancestor_id (ancestor_id)
);订单表 (orders)代码语言:javascript复制CREATE TABLE orders (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
order_no VARCHAR(50) NOT NULL UNIQUE,
user_id BIGINT NOT NULL,
total_amount DECIMAL(10,2) NOT NULL COMMENT '订单总金额',
actual_amount DECIMAL(10,2) NOT NULL COMMENT '实际支付金额',
commission_base DECIMAL(10,2) NOT NULL COMMENT '分佣基数',
status TINYINT NOT NULL COMMENT '订单状态',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_user_id (user_id),
INDEX idx_created_at (created_at)
);分佣记录表 (commission_records)代码语言:javascript复制CREATE TABLE commission_records (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
order_id BIGINT NOT NULL,
user_id BIGINT NOT NULL COMMENT '获得佣金的用户',
from_user_id BIGINT NOT NULL COMMENT '来源用户',
commission_level INT NOT NULL COMMENT '分佣层级',
commission_rate DECIMAL(5,4) NOT NULL COMMENT '分佣比例',
commission_amount DECIMAL(10,2) NOT NULL COMMENT '分佣金额',
commission_base DECIMAL(10,2) NOT NULL COMMENT '分佣基数',
status TINYINT NOT NULL COMMENT '1-待结算 2-已结算 3-已取消',
settled_at TIMESTAMP NULL COMMENT '结算时间',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_user_id (user_id),
INDEX idx_order_id (order_id),
INDEX idx_status (status)
);分佣规则表 (commission_rules)代码语言:javascript复制CREATE TABLE commission_rules (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
rule_name VARCHAR(100) NOT NULL,
rule_type TINYINT NOT NULL COMMENT '1-固定比例 2-阶梯比例 3-固定金额',
level_config JSON NOT NULL COMMENT '层级配置',
product_categories JSON COMMENT '适用商品分类',
status TINYINT DEFAULT 1,
start_time TIMESTAMP NULL,
end_time TIMESTAMP NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);4. 核心代码实现4.1 分销关系管理代码语言:javascript复制@Service
@Slf4j
public class DistributionRelationService {
@Autowired
private DistributionRelationMapper relationMapper;
@Autowired
private UserMapper userMapper;
/**
* 建立分销关系
*/
@Transactional
public void buildDistributionRelation(Long userId, String inviteCode) {
// 1. 验证邀请码
User parentUser = userMapper.selectByInviteCode(inviteCode);
if (parentUser == null) {
throw new BusinessException("无效的邀请码");
}
// 2. 防止循环引用
if (userId.equals(parentUser.getId())) {
throw new BusinessException("不能邀请自己");
}
// 3. 更新用户的直接上级
User currentUser = userMapper.selectById(userId);
currentUser.setParentId(parentUser.getId());
userMapper.updateById(currentUser);
// 4. 建立多级关系链
buildRelationChain(userId, parentUser.getId());
}
/**
* 构建完整的关系链
*/
private void buildRelationChain(Long userId, Long parentId) {
// 获取上级的所有祖先关系
List
relationMapper.selectByUserId(parentId);
List
// 添加直接上级关系
DistributionRelation directRelation = new DistributionRelation();
directRelation.setUserId(userId);
directRelation.setAncestorId(parentId);
directRelation.setLevel(1);
newRelations.add(directRelation);
// 添加上级的祖先关系
for (DistributionRelation parentRelation : parentRelations) {
DistributionRelation relation = new DistributionRelation();
relation.setUserId(userId);
relation.setAncestorId(parentRelation.getAncestorId());
relation.setLevel(parentRelation.getLevel() + 1);
newRelations.add(relation);
}
// 批量插入关系
relationMapper.batchInsert(newRelations);
// 更新用户层级
User user = userMapper.selectById(userId);
user.setDistributionLevel(getMaxLevel(newRelations));
userMapper.updateById(user);
}
/**
* 获取用户的所有下级
*/
public List
return relationMapper.selectSubordinateUserIds(userId, maxLevel);
}
}4.2 分佣规则引擎代码语言:javascript复制@Service
public class CommissionRuleEngine {
@Autowired
private CommissionRuleMapper ruleMapper;
/**
* 计算分佣
*/
public List
// 1. 获取适用的分佣规则
CommissionRule rule = getApplicableRule(order);
// 2. 获取分销关系链
List
relationMapper.selectByUserId(distributorId);
// 3. 根据规则类型计算分佣
List
switch (rule.getRuleType()) {
case FIXED_RATE:
commissionDetails = calculateFixedRateCommission(order, relations, rule);
break;
case LADDER_RATE:
commissionDetails = calculateLadderRateCommission(order, relations, rule);
break;
case FIXED_AMOUNT:
commissionDetails = calculateFixedAmountCommission(order, relations, rule);
break;
}
return commissionDetails;
}
/**
* 固定比例分佣计算
*/
private List
Order order,
List
CommissionRule rule) {
List
JSONObject levelConfig = JSON.parseObject(rule.getLevelConfig());
for (DistributionRelation relation : relations) {
String levelKey = "level_" + relation.getLevel();
if (levelConfig.containsKey(levelKey)) {
BigDecimal rate = levelConfig.getBigDecimal(levelKey);
BigDecimal amount = order.getCommissionBase().multiply(rate);
if (amount.compareTo(BigDecimal.ZERO) > 0) {
CommissionDetail detail = new CommissionDetail();
detail.setUserId(relation.getAncestorId());
detail.setFromUserId(order.getUserId());
detail.setCommissionLevel(relation.getLevel());
detail.setCommissionRate(rate);
detail.setCommissionAmount(amount);
detail.setCommissionBase(order.getCommissionBase());
details.add(detail);
}
}
}
return details;
}
/**
* 阶梯比例分佣计算
*/
private List
Order order,
List
CommissionRule rule) {
List
JSONArray ladderConfig = JSON.parseArray(rule.getLevelConfig());
// 按订单金额匹配阶梯
BigDecimal orderAmount = order.getActualAmount();
JSONObject matchedLadder = findMatchedLadder(ladderConfig, orderAmount);
if (matchedLadder != null) {
JSONObject rates = matchedLadder.getJSONObject("rates");
for (DistributionRelation relation : relations) {
String levelKey = "level_" + relation.getLevel();
if (rates.containsKey(levelKey)) {
BigDecimal rate = rates.getBigDecimal(levelKey);
BigDecimal amount = order.getCommissionBase().multiply(rate);
if (amount.compareTo(BigDecimal.ZERO) > 0) {
CommissionDetail detail = buildCommissionDetail(
order, relation, rate, amount);
details.add(detail);
}
}
}
}
return details;
}
private JSONObject findMatchedLadder(JSONArray ladderConfig, BigDecimal orderAmount) {
for (int i = 0; i < ladderConfig.size(); i++) {
JSONObject ladder = ladderConfig.getJSONObject(i);
BigDecimal minAmount = ladder.getBigDecimal("minAmount");
BigDecimal maxAmount = ladder.getBigDecimal("maxAmount");
if (orderAmount.compareTo(minAmount) >= 0 &&
(maxAmount == null || orderAmount.compareTo(maxAmount) < 0)) {
return ladder;
}
}
return null;
}
}4.3 分佣执行服务代码语言:javascript复制@Service
@Slf4j
public class CommissionService {
@Autowired
private CommissionRecordMapper commissionRecordMapper;
@Autowired
private DistributionRelationService relationService;
@Autowired
private CommissionRuleEngine ruleEngine;
/**
* 处理订单分佣
*/
@Transactional
public void processOrderCommission(Order order) {
// 1. 检查订单是否满足分佣条件
if (!shouldProcessCommission(order)) {
return;
}
// 2. 获取分销用户(订单用户)
Long distributorId = order.getUserId();
// 3. 计算分佣详情
List
ruleEngine.calculateCommission(order, distributorId);
// 4. 保存分佣记录
List
for (CommissionDetail detail : commissionDetails) {
CommissionRecord record = buildCommissionRecord(order, detail);
records.add(record);
}
commissionRecordMapper.batchInsert(records);
log.info("订单分佣处理完成,订单ID: {}, 分佣记录数: {}",
order.getId(), records.size());
}
/**
* 判断是否应该处理分佣
*/
private boolean shouldProcessCommission(Order order) {
// 只对已支付的订单进行分佣
if (!OrderStatus.PAID.equals(order.getStatus())) {
return false;
}
// 检查分佣基数是否大于0
if (order.getCommissionBase().compareTo(BigDecimal.ZERO) <= 0) {
return false;
}
// 检查用户是否是分销员
User user = userMapper.selectById(order.getUserId());
return user != null && UserType.DISTRIBUTOR.equals(user.getUserType());
}
/**
* 构建分佣记录
*/
private CommissionRecord buildCommissionRecord(Order order, CommissionDetail detail) {
CommissionRecord record = new CommissionRecord();
record.setOrderId(order.getId());
record.setUserId(detail.getUserId());
record.setFromUserId(detail.getFromUserId());
record.setCommissionLevel(detail.getCommissionLevel());
record.setCommissionRate(detail.getCommissionRate());
record.setCommissionAmount(detail.getCommissionAmount());
record.setCommissionBase(detail.getCommissionBase());
record.setStatus(CommissionStatus.PENDING);
return record;
}
/**
* 结算分佣
*/
@Transactional
public void settleCommissions(List
List
for (CommissionRecord record : records) {
if (CommissionStatus.PENDING.equals(record.getStatus())) {
// 更新记录状态
record.setStatus(CommissionStatus.SETTLED);
record.setSettledAt(new Date());
commissionRecordMapper.updateById(record);
// 实际资金操作(调用支付服务)
transferCommission(record);
}
}
}
/**
* 资金转账(简化实现)
*/
private void transferCommission(CommissionRecord record) {
// 调用支付系统API或更新用户余额
log.info("分佣转账: 用户 {} 获得佣金 {}",
record.getUserId(), record.getCommissionAmount());
}
}5. 分佣规则设计5.1 常见分佣模式5.1.1 固定比例模式代码语言:javascript复制{
"rule_type": "FIXED_RATE",
"level_config": {
"level_1": 0.10,
"level_2": 0.05,
"level_3": 0.03
}
}5.1.2 阶梯比例模式代码语言:javascript复制{
"rule_type": "LADDER_RATE",
"level_config": [
{
"minAmount": 0,
"maxAmount": 100,
"rates": {
"level_1": 0.08,
"level_2": 0.04
}
},
{
"minAmount": 100,
"maxAmount": 500,
"rates": {
"level_1": 0.12,
"level_2": 0.06,
"level_3": 0.03
}
}
]
}5.1.3 团队业绩模式代码语言:javascript复制// 基于团队总业绩的分佣
public class TeamPerformanceRule {
private Map
private Map
public List
Order order,
User distributor,
TeamPerformance performance) {
// 计算个人业绩分佣
BigDecimal personalRate = getPersonalRate(performance.getPersonalSales());
BigDecimal personalCommission = order.getCommissionBase().multiply(personalRate);
// 计算团队管理分佣
BigDecimal teamRate = getTeamRate(performance.getTeamSales());
BigDecimal teamCommission = order.getCommissionBase().multiply(teamRate);
// 返回组合分佣
List
// ... 构建分佣详情
return details;
}
}5.2 防作弊机制代码语言:javascript复制@Service
public class AntiCheatService {
/**
* 分佣风控检查
*/
public CommissionRiskCheckResult riskCheck(Order order, List
CommissionRiskCheckResult result = new CommissionRiskCheckResult();
// 1. 自买自卖检测
if (isSelfTrading(order, details)) {
result.setHighRisk(true);
result.addRiskItem("自买自卖风险");
}
// 2. 异常关系链检测
if (hasAbnormalRelationChain(order.getUserId())) {
result.setHighRisk(true);
result.addRiskItem("异常关系链");
}
// 3. 高频交易检测
if (isHighFrequencyTrading(order.getUserId())) {
result.setMediumRisk(true);
result.addRiskItem("高频交易");
}
return result;
}
/**
* 自买自卖检测
*/
private boolean isSelfTrading(Order order, List
for (CommissionDetail detail : details) {
if (detail.getUserId().equals(order.getUserId())) {
return true;
}
}
return false;
}
}6. 性能优化方案6.1 数据库优化代码语言:javascript复制-- 添加合适的索引
CREATE INDEX idx_commission_user_status ON commission_records(user_id, status);
CREATE INDEX idx_relations_user_ancestor ON distribution_relations(user_id, ancestor_id);
CREATE INDEX idx_orders_user_created ON orders(user_id, created_at);
-- 分区表(按时间分区)
ALTER TABLE commission_records PARTITION BY RANGE (YEAR(created_at)) (
PARTITION p2023 VALUES LESS THAN (2024),
PARTITION p2024 VALUES LESS THAN (2025)
);6.2 缓存策略代码语言:javascript复制@Service
public class DistributionCacheService {
@Autowired
private RedisTemplate redisTemplate;
private static final String RELATION_CACHE_KEY = "dist:relation:%s";
private static final long RELATION_CACHE_TTL = 3600; // 1小时
/**
* 缓存用户关系链
*/
public void cacheUserRelations(Long userId, List
String key = String.format(RELATION_CACHE_KEY, userId);
redisTemplate.opsForValue().set(key, relations, RELATION_CACHE_TTL, TimeUnit.SECONDS);
}
/**
* 从缓存获取关系链
*/
public List
String key = String.format(RELATION_CACHE_KEY, userId);
return (List
}
}7. 总结本文详细介绍了分销系统的整体架构设计、数据库模型、核心代码实现以及分佣规则设计。关键要点包括:
架构清晰:采用分层架构,模块化设计关系管理:使用闭包表模式存储多级分销关系规则灵活:支持多种分佣模式,可配置化风控完善:内置防作弊机制,保障系统安全性能优化:通过缓存、索引等手段提升系统性能实际项目中还需要考虑分布式事务、数据一致性、系统监控等更多细节,但以上设计已经提供了一个坚实的分销系统基础框架。