← 返回首页
💼

社交架构:Feed流、消息推送与关系链

📂 architecture ⏱ 3 min 403 words

社交架构:Feed流、消息推送与关系链

社交系统架构概览

社交系统的核心是用户关系和内容分发。主要模块包括:用户系统、关系链、Feed流、消息推送、内容存储、推荐系统。

社交系统架构:

接入层:负载均衡、API网关、限流
业务层:
  - 用户服务:注册、登录、资料管理
  - 关注服务:关注、取关、关系查询
  - Feed服务:Feed流生成、分发、排序
  - 消息服务:私信、通知、推送
  - 内容服务:图文、视频、动态
  - 推荐服务:内容推荐、用户推荐
数据层:MySQL、Redis、HBase、Elasticsearch

Feed流架构设计

Feed流是社交系统的核心,需要根据用户关注关系生成个性化的时间线。常见的方案有推模式、拉模式、推拉结合。

三种Feed流方案对比:

推模式(写扩散):
  原理:用户发布内容时,推送到所有粉丝的Feed流
  优点:读取快,直接返回
  缺点:写放大,大V问题严重
  适用:粉丝数有上限的场景

拉模式(读扩散):
  原理:用户请求Feed时,实时拉取所有关注者的最新内容
  优点:写入简单,无数据冗余
  缺点:读取慢,需要实时计算
  适用:粉丝数少,关注数多的场景

推拉结合:
  原理:普通用户用推模式,大V用拉模式
  优点:平衡读写性能
  缺点:实现复杂,需要区分用户类型
  适用:主流社交平台
// Feed流生成服务
@Service
public class FeedService {
    @Autowired
    private FeedRepository feedRepository;
    @Autowired
    private FollowService followService;
    
    // 推模式:发布时推送到粉丝Feed
    public void publishFeed(UserPost post) {
        // 1. 保存帖子
        feedRepository.savePost(post);
        
        // 2. 获取粉丝列表
        List<Long> followers = followService.getFollowers(post.getUserId());
        
        // 3. 推送到粉丝Feed
        for (Long followerId : followers) {
            feedRepository.pushToFeed(followerId, post.getId());
        }
    }
    
    // 拉模式:请求时实时生成
    public List<FeedItem> getFeed(Long userId, int page, int size) {
        // 1. 获取关注列表
        List<Long> following = followService.getFollowing(userId);
        
        // 2. 拉取每个关注者的最新帖子
        List<FeedItem> items = new ArrayList<>();
        for (Long followeeId : following) {
            List<Post> posts = feedRepository.getLatestPosts(followeeId, 10);
            items.addAll(convertToFeedItems(posts));
        }
        
        // 3. 排序和分页
        items.sort(Comparator.comparing(FeedItem::getCreateTime).reversed());
        return paginate(items, page, size);
    }
}

关系链存储设计

社交系统的关系链是核心数据,需要支持高效的关注/取关、粉丝查询、共同好友等操作。

# 关系链存储方案
class RelationshipService:
    def __init__(self):
        self.mysql = MySQLStorage()      # 持久化存储
        self.redis = RedisCache()        # 热点数据缓存
    
    def follow(self, user_id, target_id):
        # 1. 写入MySQL
        self.mysql.insert_follow(user_id, target_id)
        
        # 2. 更新Redis缓存
        self.redis.add_following(user_id, target_id)
        self.redis.add_follower(target_id, user_id)
        
        # 3. 异步更新Feed流
        self.async_update_feed(user_id, target_id)
    
    def get_following(self, user_id):
        # 优先从Redis读取
        following = self.redis.get_following(user_id)
        if following is None:
            following = self.mysql.get_following(user_id)
            self.redis.set_following(user_id, following, ttl=3600)
        return following
    
    def get_common_friends(self, user_id1, user_id2):
        # 获取共同好友
        following1 = set(self.get_following(user_id1))
        following2 = set(self.get_following(user_id2))
        return list(following1.intersection(following2))

消息推送架构

消息推送需要支持多种推送渠道(站内信、App推送、短信、邮件),并保证消息的可靠投递。

// 消息推送服务
@Service
public class NotificationService {
    @Autowired
    private MessageQueue mq;
    @Autowired
    private PushChannelRegistry channels;
    
    public void sendNotification(Notification notification) {
        // 1. 持久化消息
        saveNotification(notification);
        
        // 2. 根据用户设置选择推送渠道
        List<PushChannel> userChannels = getUserChannels(
            notification.getUserId(), 
            notification.getType()
        );
        
        // 3. 通过消息队列异步推送
        for (PushChannel channel : userChannels) {
            PushMessage message = PushMessage.builder()
                .channel(channel)
                .userId(notification.getUserId())
                .title(notification.getTitle())
                .content(notification.getContent())
                .build();
            
            mq.send("push-topic", message);
        }
    }
}

// 推送渠道注册
@Component
public class PushChannelRegistry {
    private final Map<String, PushChannel> channels = new HashMap<>();
    
    @PostConstruct
    public void init() {
        channels.put("app", new AppPushChannel());
        channels.put("sms", new SmsPushChannel());
        channels.put("email", new EmailPushChannel());
        channels.put("web", new WebPushChannel());
    }
    
    public PushChannel getChannel(String channelType) {
        return channels.get(channelType);
    }
}

内容存储设计

社交内容包括文字、图片、视频等多种类型,需要设计合理的存储方案。

# 内容存储分层设计
class ContentStorage:
    def __init__(self):
        self.mysql = MySQLStorage()        # 元数据
        self.redis = RedisCache()          # 热点内容
        self.s3 = S3Storage()             # 文件存储
        self.cdn = CDNService()           # 内容分发
    
    def save_content(self, content):
        # 1. 保存元数据到MySQL
        content_id = self.mysql.save_metadata(content)
        
        # 2. 上传文件到S3
        if content.has_media():
            file_url = self.s3.upload(content.get_media())
            content.set_media_url(file_url)
        
        # 3. 更新MySQL中的文件URL
        self.mysql.update_media_url(content_id, file_url)
        
        # 4. 加入Redis热点缓存
        self.redis.cache_content(content_id, content, ttl=3600)
        
        return content_id
    
    def get_content(self, content_id):
        # 优先从Redis读取
        content = self.redis.get_content(content_id)
        if content is None:
            content = self.mysql.get_content(content_id)
            if content:
                self.redis.cache_content(content_id, content, ttl=3600)
        
        # 通过CDN返回文件URL
        if content and content.has_media():
            content.set_media_url(self.cdn.get_url(content.get_media_url()))
        
        return content

社交系统性能优化

社交系统的性能优化重点在于热点数据处理和缓存策略。

性能优化策略:

热点数据缓存:
  - 用户资料缓存(Redis)
  - 关注关系缓存(Redis)
  - 热门内容缓存(Redis + CDN)
  - Feed流缓存(Redis Sorted Set)

数据库优化:
  - 读写分离
  - 分库分表(按用户ID)
  - 索引优化
  - 热点数据预加载

异步处理:
  - Feed流异步生成
  - 消息推送异步处理
  - 内容审核异步进行
  - 统计数据异步计算

限流降级:
  - 接口限流
  - 热点用户降级
  - 推送服务降级
  - 搜索服务降级