<think>
我们参考了多个引用中关于点赞、分享、收藏表设计的信息,特别是引用[2]和引用[4]提供了具体的表结构设计思路。
引用[2]提到点赞表的设计包含了类型字段(type)用于区分是作品点赞还是评论点赞,以及状态字段(status)表示点赞是否有效。
引用[4]则提到对于论坛文章,可以设计一个表来记录用户对文章的点赞、分享和收藏,并且记录时间,同时分享还需要记录通过分享链接进入的用户以判断分享是否有效。
根据这些信息,我们可以设计一个通用的方案,将点赞、分享、收藏设计在同一张表中,通过一个操作类型字段来区分,也可以分开设计。
考虑到点赞、分享、收藏虽然都是用户行为,但它们的业务逻辑有所不同(例如分享需要跟踪后续访问,而点赞和收藏不需要),且发生频率可能很高,我们有两种常见方案:
方案一:分开设计
1. 点赞表(like):
id (主键)
target_id (目标id,可以是作品、评论等)
target_type (目标类型,如:1-文章,2-评论)
user_id (用户id)
status (状态,0-取消,1-有效)
create_time (创建时间)
update_time (更新时间)
2. 收藏表(favorite):
id (主键)
target_id
target_type
user_id
status (0-取消收藏,1-已收藏)
create_time
update_time
3. 分享表(share):
id (主键)
target_id (分享的目标,如文章id)
user_id (分享者id)
share_time (分享时间)
share_channel (分享渠道,如微信、微博等)
# 另外,为了追踪分享效果,需要记录通过该分享链接进入的用户访问记录,单独设计一张表:
分享访问记录表(share_visit):
id (主键)
share_id (对应分享表的id)
visitor_id (访问者用户id,可为null,如果未登录则记录为null)
visit_time (访问时间)
ip_address (访问ip)
方案二:统一设计(操作类型字段区分)
用户行为表(user_action):
id (主键)
user_id (用户id)
target_id (目标id)
target_type (目标类型,如文章、评论)
action_type (操作类型:1-点赞,2-收藏,3-分享)
action_value (操作的值,对于点赞和收藏可以用1/0表示有效/取消,对于分享则每次都是新增一条记录,不需要取消状态?)
create_time
update_time
但是分享行为比较特殊,它需要记录渠道和追踪后续的访问,所以统一表可能不太适合分享行为。因此,通常分享会单独设计。
综合考虑,我们采用方案一,因为:
1. 点赞和收藏都有状态(取消和有效),而分享通常是一次性事件(用户分享出去后,我们只需记录分享事件,然后追踪访问)。
2. 分享需要额外记录访问情况,单独设计更清晰。
优化考虑:
- 对于高并发场景(如微博点赞),引用[3]提到不会直接写关系数据库,而是通过消息队列异步处理,并且计数会先更新本地缓存(如Redis),然后异步持久化到数据库。
- 因此,我们在设计表的同时,也要考虑在应用层使用缓存和异步队列来保证性能。
具体设计如下:
1. 点赞表(like):
字段名 类型 说明
id bigint 主键,自增
target_id bigint 被点赞的目标id(如文章id、评论id)
target_type tinyint 目标类型:1-文章,2-评论,3-...(根据业务扩展)
user_id bigint 用户id
status tinyint 状态:0-取消点赞,1-有效点赞
create_time datetime 创建时间
update_time datetime 更新时间
唯一索引:uk_target_user (target_id, target_type, user_id) 防止重复点赞
2. 收藏表(favorite):
字段名 类型 说明
id bigint 主键,自增
target_id bigint 被收藏的目标id
target_type tinyint 目标类型:1-文章,2-评论,...
user_id bigint 用户id
status tinyint 状态:0-取消收藏,1-已收藏
create_time datetime 创建时间
update_time datetime 更新时间
唯一索引:uk_target_user (target_id, target_type, user_id)
3. 分享表(share):
字段名 类型 说明
id bigint 主键,自增
target_id bigint 被分享的目标id(如文章id)
target_type tinyint 目标类型:1-文章,...
user_id bigint 分享者用户id
share_time datetime 分享时间
share_channel varchar(20) 分享渠道(如:微信、微博、QQ等)
share_token varchar(32) 分享的唯一标识(用于生成分享链接,可选)
索引:idx_target (target_id, target_type) 和 idx_user (user_id)
4. 分享访问记录表(share_visit):
字段名 类型 说明
id bigint 主键,自增
share_id bigint 对应的分享id(外键关联share表id)
visitor_id bigint 访问者用户id(如果未登录则为null)
visit_time datetime 访问时间
ip_address varchar(45) 访问IP(支持IPv6)
索引:idx_share (share_id) 和 idx_visit_time (visit_time)
关于计数:
为了快速获取某个目标的点赞数、收藏数,我们可以:
1. 在目标表中增加计数器字段(如文章表增加like_count, favorite_count),通过异步更新。
2. 或者单独维护计数表(计数表需要根据target_id和target_type来统计,在高并发下用Redis缓存计数,然后定时同步到数据库)。
引用[3]中提到,点赞总数本地和后端分开,即用户点赞后本地立即显示变化,然后异步更新后端。因此,我们可以使用Redis来存储每个目标的点赞数、收藏数,然后定时持久化到数据库的计数表中(或更新文章表的计数字段)。
总结:
以上设计方案是一个通用的基础方案,在实际项目中可能还需要根据业务需求进行调整。例如,如果业务中分享不需要追踪访问,则可以简化分享表的设计。
相关问题:
1. 如何设计高并发的点赞系统?
2. 如何实现分享链接的追踪?
3. 收藏功能与点赞功能在设计上有什么异同?
4. 如何保证用户行为数据(点赞、收藏、分享)的一致性?
</think>
### 点赞、分享、收藏表设计方案
根据引用资料的分析,以下是优化的数据库设计方案,支持高并发场景并满足业务需求:
#### 1. **统一行为记录表(推荐)**
```sql
CREATE TABLE user_action (
id BIGINT PRIMARY KEY AUTO_INCREMENT, -- 主键
user_id BIGINT NOT NULL, -- 用户ID
target_id BIGINT NOT NULL, -- 目标ID(文章/评论)
target_type TINYINT NOT NULL, -- 目标类型:1-文章 2-评论 3-分享
action_type TINYINT NOT NULL, -- 行为类型:1-点赞 2-收藏 3-分享
status TINYINT DEFAULT 1, -- 状态:0-取消 1-有效
channel VARCHAR(20) DEFAULT NULL, -- 分享渠道(微信/微博等)
create_time DATETIME NOT NULL, -- 创建时间
update_time DATETIME NOT NULL -- 更新时间
);
```
**设计说明**:
- 使用`target_type`区分行为对象(文章/评论/分享),引用[2][^2]
- `status`字段支持点赞/收藏的取消操作,避免物理删除
- `channel`字段记录分享渠道,满足裂变分析需求,引用[4][^4]
- **唯一索引**:`UNIQUE KEY uk_user_target (user_id, target_id, action_type)` 防止重复行为
#### 2. **分享追踪表(独立设计)**
```sql
CREATE TABLE share_trace (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
share_id BIGINT NOT NULL, -- 关联user_action的分享记录ID
visitor_id BIGINT DEFAULT NULL, -- 访问者ID(未登录为null)
ip_address VARCHAR(45) NOT NULL, -- 访问者IP
visit_time DATETIME NOT NULL -- 访问时间
);
```
**设计说明**:
- 记录通过分享链接进入的行为,验证分享有效性,引用[4][^4]
- 用于裂变营销的数据分析(如计算分享转化率)
#### 3. **计数优化方案**
```sql
-- 文章/评论基础表添加计数字段
ALTER TABLE article ADD COLUMN like_count INT DEFAULT 0;
ALTER TABLE article ADD COLUMN share_count INT DEFAULT 0;
ALTER TABLE comment ADD COLUMN like_count INT DEFAULT 0;
```
**高并发处理**:
1. 用户操作时**先更新Redis缓存**:`INCR article:123:like_count`
2. 异步队列持久化:通过消息队列(如Kafka)批量更新数据库,引用[3][^3]
3. 定时任务补偿:每小时同步Redis计数到数据库
#### 关键设计原则
1. **状态字段代替删除**
`status`标记取消行为,保留历史数据便于分析
2. **读写分离**
- 写操作:优先处理Redis和消息队列
- 读操作:热点数据从Redis读取计数
3. **分表策略**
按月分表存储`user_action`,避免单表过大(如`user_action_2023_07`)
4. **数据验证**
```sql
-- 检查用户是否已点赞
SELECT status FROM user_action
WHERE user_id=1001 AND target_id=2002 AND action_type=1;
```
---
### 典型应用场景
1. **点赞/取消点赞**
```sql
INSERT INTO user_action(user_id,target_id,target_type,action_type,create_time)
VALUES (1001, 2002, 1, 1, NOW())
ON DUPLICATE KEY UPDATE status=IF(status=0,1,0);
```
2. **分享追踪**
```sql
/* 记录分享行为 */
INSERT INTO user_action(user_id,target_id,action_type,channel)
VALUES (1001, 2002, 3, 'WeChat');
/* 记录分享后访问 */
INSERT INTO share_trace(share_id, ip_address, visit_time)
VALUES (LAST_INSERT_ID(), '192.168.1.1', NOW());
```
---
### 性能优化建议
1. **缓存层**
- 使用Redis存储用户最新行为:`SET user:1001:like_article_2002 1`
- 布隆过滤器快速判断是否存在行为记录
2. **异步处理**
```mermaid
graph LR
A[用户点击点赞] --> B{Redis检查}
B -->|通过| C[更新Redis计数]
C --> D[发送MQ消息]
D --> E[MySQL异步消费]
```
3. **数据分片**
按`user_id`哈希分库分表,缓解写入压力
---