分销系统是一种基于社交关系的电商营销模式,通过多级分销网络实现商品推广和销售。本文将详细介绍分销系统的技术架构、数据库设计和分佣规则实现。
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ 客户端层 │ │ API网关 │ │ 业务服务层 │
│ - Web前端 │───▶│ - 路由转发 │───▶│ - 用户服务 │
│ - 移动APP │ │ - 认证鉴权 │ │ - 商品服务 │
│ - 小程序 │ │ - 限流熔断 │ │ - 订单服务 │
└─────────────────┘ └──────────────────┘ └─────────────────┘
│
▼
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ 数据存储层 │◀──│ 数据访问层 │◀──│ 分销服务层 │
│ - MySQL │ │ - MyBatis │ │ - 关系管理 │
│ - Redis │ │ - JPA │ │ - 分佣计算 │
│ - Elasticsearch │ │ - Redis Template │ │ - 结算服务 │
└─────────────────┘ └──────────────────┘ └─────────────────┘// 分销系统核心服务类图
public class DistributionSystem {
// 用户服务
UserService userService;
// 分销关系服务
DistributionRelationService relationService;
// 分佣服务
CommissionService commissionService;
// 结算服务
SettlementService settlementService;
// 规则引擎
RuleEngine ruleEngine;
}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)
);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)
);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)
);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)
);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
);@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<DistributionRelation> parentRelations =
relationMapper.selectByUserId(parentId);
List<DistributionRelation> newRelations = new ArrayList<>();
// 添加直接上级关系
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<Long> getSubordinateUsers(Long userId, Integer maxLevel) {
return relationMapper.selectSubordinateUserIds(userId, maxLevel);
}
}@Service
public class CommissionRuleEngine {
@Autowired
private CommissionRuleMapper ruleMapper;
/**
* 计算分佣
*/
public List<CommissionDetail> calculateCommission(Order order, Long distributorId) {
// 1. 获取适用的分佣规则
CommissionRule rule = getApplicableRule(order);
// 2. 获取分销关系链
List<DistributionRelation> relations =
relationMapper.selectByUserId(distributorId);
// 3. 根据规则类型计算分佣
List<CommissionDetail> commissionDetails = new ArrayList<>();
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<CommissionDetail> calculateFixedRateCommission(
Order order,
List<DistributionRelation> relations,
CommissionRule rule) {
List<CommissionDetail> details = new ArrayList<>();
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<CommissionDetail> calculateLadderRateCommission(
Order order,
List<DistributionRelation> relations,
CommissionRule rule) {
List<CommissionDetail> details = new ArrayList<>();
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;
}
}@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<CommissionDetail> commissionDetails =
ruleEngine.calculateCommission(order, distributorId);
// 4. 保存分佣记录
List<CommissionRecord> records = new ArrayList<>();
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<Long> recordIds) {
List<CommissionRecord> records = commissionRecordMapper.selectByIds(recordIds);
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());
}
}{
"rule_type": "FIXED_RATE",
"level_config": {
"level_1": 0.10,
"level_2": 0.05,
"level_3": 0.03
}
}{
"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
}
}
]
}// 基于团队总业绩的分佣
public class TeamPerformanceRule {
private Map<String, BigDecimal> performanceRates;
private Map<String, BigDecimal> teamRates;
public List<CommissionDetail> calculateTeamCommission(
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<CommissionDetail> details = new ArrayList<>();
// ... 构建分佣详情
return details;
}
}@Service
public class AntiCheatService {
/**
* 分佣风控检查
*/
public CommissionRiskCheckResult riskCheck(Order order, List<CommissionDetail> details) {
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<CommissionDetail> details) {
for (CommissionDetail detail : details) {
if (detail.getUserId().equals(order.getUserId())) {
return true;
}
}
return false;
}
}-- 添加合适的索引
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)
);@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<DistributionRelation> relations) {
String key = String.format(RELATION_CACHE_KEY, userId);
redisTemplate.opsForValue().set(key, relations, RELATION_CACHE_TTL, TimeUnit.SECONDS);
}
/**
* 从缓存获取关系链
*/
public List<DistributionRelation> getCachedUserRelations(Long userId) {
String key = String.format(RELATION_CACHE_KEY, userId);
return (List<DistributionRelation>) redisTemplate.opsForValue().get(key);
}
}本文详细介绍了分销系统的整体架构设计、数据库模型、核心代码实现以及分佣规则设计。关键要点包括:
实际项目中还需要考虑分布式事务、数据一致性、系统监控等更多细节,但以上设计已经提供了一个坚实的分销系统基础框架。