社交类网站设计:经典feed流系统架构详细设计(小红书微博等)

news2025/5/31 17:38:47

文章目录

  • 一、关注服务
    • 1、粉丝、关注数架构设计
      • (1)数据库实现方案1
      • (2)数据库实现方案2
      • (3)基于redis缓存优化
      • (4)使用专用计数服务
      • (5)近似计数(牺牲部分精度)
    • 2、粉丝、关注列表架构设计
      • (1)数据库实现方案1
      • (2)数据库实现方案2:分库分表不友好
      • (3)关注与粉丝列表缓存
      • (4)业务层面优化
      • (5)用户自己查询列表:不做限制
      • (6)代码落地
    • 3、高性能关注服务架构设计
      • (1)热点事件读并发高
      • (2)热点事件写并发高
      • (3)大数据量关系链表分库分表:普通用户/大V
      • (4)大V爆火数据库优化
  • 二、点赞计数服务
    • 1、通用计数服务设计
      • (1)DB写,缓存读(有性能限制,计数精准)
      • (2)缓存读写,批量入库(性能高,redis宕机计数不精准)
      • (3)扩展:通用计数功能DB优化
      • (4)计数服务如何分库分表?
      • (5)引入MQ缓冲异步入库
    • 2、高并发计数服务架构设计
      • (1)异步数据入库
      • (2)爆火帖子流量处理
      • (3)大数据量下判断用户是否已经点赞
      • (4)大数据量下查看点赞用户详情
  • 三、帖子服务架构设计
    • 1、帖子基本功能设计
      • (1)帖子数据库设计
      • (2)帖子查看架构设计
      • (3)发帖子功能设计
    • 2、帖子高性能架构设计
      • (1)上亿帖子分库分表
      • (2)redis缓存设计1:用户维度缓存(查询个人帖子列表)
      • (3)redis缓存设计2:时间维度缓存(参考Feed流)
      • (4)帖子列表查询功能(用户维度/时间维度/频道维度)(参考Feed流)
      • (5)帖子详情查看
    • 3、Feed流架构设计
      • (1)Feed流简介
      • (2)pull模式
      • (3)push模式(对查询进行优化)
      • (4)push和pull模式优化
      • (5)发帖、读贴流程及缓存架构设计
  • 四、附近的人架构设计
    • 1、架构设计
  • 五、评论服务架构设计
    • 1、什么是评论系统
    • 2、评论系统基本功能设计
      • (1)数据库设计与选型
      • (2)基本功能实现
    • 3、高性能评论系统架构设计
      • (1)基于mysql+redis缓存架构设计
      • (2)分库分表或者使用NewSQL
      • (3)高性能判断是否给评论点赞
  • 六、签到服务架构设计
    • 1、基本功能设计

一、关注服务

1、粉丝、关注数架构设计

在这里插入图片描述

(1)数据库实现方案1

fllower表记录被哪些用户关注(id、userId:用户ID、fllowerId:粉丝ID)
attention表记录当前用户关注了哪些用户(id、userId:用户ID、attentionId:关注用户ID)

-- 查询用户详细信息,首页需要显示用户头像、昵称等信息
select * from user where id=1;
-- 查询粉丝数
select count(1) from fllower where userId=1;
-- 查询关注数
select count(1) from attention where userId=1;

除了用户基本信息以外,还需要额外sql查询粉丝数和关注数。
如果表数据不多的话,粉丝数和关注查询的话,性能还是可以的。
但是单个表的数据会越来越多,而且关系网非常庞大,数据量会呈指数级上升,基于数据库很快会达到性能瓶颈的。

(2)数据库实现方案2

user表(id、name、fllower_count:粉丝数、attention_count:关注数)
user表新增粉丝数和关注数字段,查询方便了,但是每次关注和被关注,都需要在user表里(关注者和被关注者都要操作)对应数量加减。
可以同一事务中进行加减,也可以用MQ异步加减,但是异步加减需要保证一致性。

-- 查询粉丝数、关注数、用户详细信息,只需要查询一次即可
select * from user where id=1;

(3)基于redis缓存优化

注意,redis只能用于缓存,并且还有过期时间
具体数据以方案2数据库中的数据为准!

fllower_count:粉丝数、attention_count:关注数,存入redis,每次关注和被关注(关注者和被关注者都要操作),在redis中增减

// 对应redis的key
user:fllower_count:1 10000
user:attention_count:1 20000

或者连带用户的信息都存入redis中,使用hash格式,hash格式也可以实现字段的自增减操作,但是用户信息修改以后,需要将缓存删除,保证缓存一致性问题

(4)使用专用计数服务

开发独立的计数服务(如 Twitter 的 Snowflake 方案变种),通过分布式计数器处理关注数和粉丝数的增减,避免数据库直接承担高并发计数压力。
- 每个用户的计数分配独立的计数器,通过 Redis 的 INCR 命令原子性更新计数。
- 定期将 Redis 中的计数批量持久化到数据库(如每10分钟同步一次),降低数据库写入频率。

(5)近似计数(牺牲部分精度)

对于非核心场景(如显示“100万+粉丝”),使用概率数据结构(如 HyperLogLog)估算粉丝数,减少内存占用和计算成本。

2、粉丝、关注列表架构设计

注意,粉丝列表和关注列表,访问频率并不会很大,主页中也只会展示粉丝数和关注数。
只有用户点击粉丝数和关注数以后,才会打开列表页面。
在这里插入图片描述

(1)数据库实现方案1

fllower表记录被哪些用户关注(id、userId:用户ID、fllowerId:粉丝ID、create_time)
attention表记录当前用户关注了哪些用户(id、userId:用户ID、attentionId:关注用户ID、create_time)

-- 查询粉丝列表,包含基本信息,并且分页、按照时间排序
select * from fllower f 
left join user u on f.userId = u.id
where userId=1 order by create_time desc limit 1,10;
-- 查询关注数,包含基本信息,并且分页、按照时间排序
select * from attention
left join user u on f.userId = u.id
where userId=1 order by create_time desc limit 1,10;

数据量多的话,查询效率肯定是非常差的,如果分页限制的话,性能会好很多。

注意,排序有可能是按照时间排序,微博是按照大V粉丝数进行排序的。

(2)数据库实现方案2:分库分表不友好

只使用一个relationship关系表(id、attentionId:关注用户ID、fllowerId:被关注者ID)
这样的话,关注操作只需要记录一张表数据即可,同时查询的话也更简单

-- 查询粉丝列表
select * from relationship r 
left join user u on r.fllowerId = u.id
where r.fllowerId=1 order by create_time desc limit 1,10;

-- 查询关注列表
select * from relationship r 
left join user u on r.attentionId = u.id
where r.attentionId=1 order by create_time desc limit 1,10;

但是分库分表不友好,因为无法确定是根据attentionId分,还是根据fllowerId分。

(3)关注与粉丝列表缓存

缓存条数200条(按需设置缓存条数)即可,加上5-10秒过期时间,因为百万粉丝的话不可能都缓存。
每次关注和取消关注,基于redis的list结构,存储用户ID,(关注者和被关注者都要操作)。
查询的时候,每次分页查询10条userId,然后通过userId来查询用户的基本信息,比如redis的mget、mysql的in操作(如果都存入redis缓存的话,更新用户信息缓存更新是不及时的)。

-- KEYS[1]为用户ID,ARGV[1]为关注者或被关注者的基本信息
-- 需要保证原子操作,虽然不一定需要保证原子性,因为最终结果一定是原子的
local size = redis.call('get', KEYS[1])
if(tonumber(size)>=200) then
	redis.call('rpop', KEYS[1])
end
redis.call('lpush', KEYS[1], ARGV[1])
return 0

如果取关的话,从redis的list直接删除对应数据,变成199条,不需要额外从数据库补充1条,因为不差那一条,而且数据过期以后会自动更新到redis,又变成200条了,更何况还会有新人关注他。

为什么是修改redis?而不是删除redis?
因为如果热门大V频繁被关注和取消关注的话,通常伴随着较大查询qps,如果直接删除缓存,可能对数据库的性能影响较大

(4)业务层面优化

用户浏览关注、粉丝列表,最多支持看200条。
比如说微博的关注粉丝列表,往下一直翻的话,就会触发限制

在这里插入图片描述

(5)用户自己查询列表:不做限制

用户查询自己,并发量并不会很高,所以可以取消缓存和查询数的设计,直接分页查库即可。

这里涉及到分页查询优化问题,深分页优化问题。

(6)代码落地

// 查询粉丝/关注列表
public List search(int userId, int type, int start, int stop) {
// 一、type=0 自己查询自己,直接查库
if (type == 0) {
	select fllower 或 attention ,查询关注列表和粉丝列表
} 

// 二、type=1 别人查询自己
if (type == 1) {
	1、先从redis查询list列表,获取userids
	2、根据userids,进行mget或者mysql的in操作,查询用户基本信息

	3、如果缓存过期,select fllower 或 attention ,查询关注列表和粉丝列表,然后存储redis中
} 

}

3、高性能关注服务架构设计

(1)热点事件读并发高

1、可以考虑使用本地缓存+redis缓存的方式,或者双重本地缓存。

使用缓存,都需要考虑缓存问题,比如说缓存与数据库的一致性、缓存雪崩、击穿、穿透问题。
从查询数据库性能优化谈到redis缓存-谈一谈缓存的穿透、雪崩、击穿

(2)热点事件写并发高

1、写并发过高,可以考虑使用MQ进行削峰填谷。

2、或者借鉴BufferTrigger缓冲区,实现请求合并、流量聚合。
流量聚合简单来说就是把多次的请求整合为一个请求处理,业务对单次的请求不敏感时并且能接受一定延迟时才能使用。
1.提供一个能存放数据的容器
2.当达到指定数量时输出容器中的数据
3.当达到指定时间时输出容器中的数据
使用场景:对大量的数据进行聚合,然后进行批量操作,适用于数据量大且相似或相同数据多的任务或者能接受一定时间内的延迟问题。

3、BufferTrigger和MQ协同使用的方式。

4、关注服务需要注意MQ顺序消费问题。(全局顺序消费、局部顺序消费)
全局顺序消费:全局只有一个queue,和一个消费者实例
局部顺序消费:通常在实际应用中,我们需要将同一个订单号(或者userId)的相关操作,按照规则(可以是hash或取模等)发送到同一个queue上,然后消费者实例,使用顺序消费模式消费消息。

注意,如果是单纯计数的话,不太需要顺序消费,因为最终的结果都是一样的。
如果是记录关注列表的话,是需要顺序消费的。取关是删除,关注是新增,如果顺序相反,会出问题。

(3)大数据量关系链表分库分表:普通用户/大V

1、为了分库分表,就需要关系链表进行区分开:
fllower表记录被哪些用户关注(id、userId:用户ID、fllowerId:粉丝ID、create_time)
attention表记录当前用户关注了哪些用户(id、userId:用户ID、attentionId:关注用户ID、create_time)
直接通过userId进行分库分表。

2、大V,几千万粉丝分库分表
大V以一张单独的表进行存储。大V认证以后,可以进行判断以后直接查询对应的数据库。

其实,主要是fllower表需要分库分表,因为一个人的粉丝可能很多,但是关注者并不会很多。

(4)大V爆火数据库优化

进行数据单独迁移:
1、配置当前数据库开关为单写
2、通过脚本迁移静态数据。迁完后,验证静态数据迁移准确性
3、配置当前数据库开关为双写(代码、binlog方式)
4、切换数据源,服务提供的数据源切换到新库

二、点赞计数服务

1、通用计数服务设计

(1)DB写,缓存读(有性能限制,计数精准)

在这里插入图片描述

(2)缓存读写,批量入库(性能高,redis宕机计数不精准)

在这里插入图片描述

点赞业务特点:
1、吞吐量高
2、能接受数据不一致

可以用MySQL做持久存储,Redis做缓存,读写操作落缓存,异步或线程定期刷新DB。
counter点赞数表:id,postld:帖子ID,count:点赞数
Redis存储:key:postld,value:count

(3)扩展:通用计数功能DB优化

一个人可能有关注数、粉丝数、总访问量。
一个帖子可能有转发量、阅读量、点赞量。

数据库表可以优化为:
couter计数表:id、userId、targetId:计数目标ID、type:计数类型(阅读数、点赞数等)、countValue:数量。
redis存储:使用hash存储

这样的话,查询一个帖子的转发数、阅读数、点赞数:

-- 数据库查询,结果为多条,根据type区分是转发数、阅读数、点赞数
select * from couter where targetId = 1;

-- redis查询
hgetall targetId

注意,该方案有一个缺点,严重依赖redis。redis宕机、异常可能会导致数据不一致。
数据少部分缺失,点赞计数服务是业务允许的。redis实现主从、主备即可。
部分精准数据(比如购买量),可以考虑第一种DB写,缓存读方案。

(4)计数服务如何分库分表?

根据userId进行分库分表。

(5)引入MQ缓冲异步入库

引入MQ、队列等缓冲组件,实现削峰填谷
在这里插入图片描述

2、高并发计数服务架构设计

(1)异步数据入库

异步任务将缓存数据写入数据库,并不需要每次轮训所有数据进行写入。
redis中数据是非常多的,如果遍历所有的key入库,对性能影响是非常大的。

可以每次写入操作,写入redis的zset,值为数据的id,并且分数设置为时间戳。
定时任务从zset中取,优先取时间最旧的,然后根据取出的id进行数据库更新操作。

(2)爆火帖子流量处理

计数服务进行模糊计数(10W+、100W+)等。
部分流量丢弃,比如自己的评论只在前端显示,其他人是看不到的。(像直播弹幕,有的弹幕并不是所有人都会看到,有可能被丢弃)

(3)大数据量下判断用户是否已经点赞

考虑使用redis:

-- 某个帖子被某个用户点赞,该方式在大数据量场景内存占用较高
set 帖子ID:用户ID 1
-- 或者使用hash格式
hset 帖子ID 用户ID 1

-- 考虑使用bitmap数据类型,该方式只能用于ID为整数的方式
setbit 帖子ID 用户ID 1
setbit 1000 100 1
-- 格式:setbit key offset value

大数据量,考虑使用布隆过滤器:布隆过滤器,如果数据不存在则一定不存在,数据存在不一定存在(有误判率)
但是,布隆过滤器是无法删除数据的。
在这里插入图片描述

(4)大数据量下查看点赞用户详情

redis中数据格式:

-- 如果每个帖子数据量太多(几十万),可以考虑分片
帖子ID(1) => [userId1, userId2 ...]
帖子ID(2) => [userId10, userId11 ...]
帖子ID(3) => [userId20, userId21 ...]

其实一般情况下,不需要查看一个帖子下面所有点赞人数的,只缓存最近的几个即可。
在这里插入图片描述

三、帖子服务架构设计

可以发布视频、图片、文本等等帖子。
不管是微博还是⼩红书,还是朋友圈等,都有⼀个最多可以发多少张图⽚的限制,所以这些app不可能让你⽆限制的发图,这样肯定对于系统资源占⽤是⽐较⼤的,并且如果是发视频的话只能发⼀个视频。
在这里插入图片描述

1、帖子基本功能设计

(1)帖子数据库设计

1、帖子主表
ID、title:标题、uid:作者ID、channel_id:频道ID、type:图文视频、labels:标签、address:图片视频地址,多个内容用逗号分隔、
发帖位置(同城搜索)、发帖经纬度(据你多远)、发帖时间、是否置顶、置顶时间

2、帖子内容表
ID、帖子ID、content:帖子内容(文案)

3、帖子点赞表
ID、帖子ID、用户ID

(2)帖子查看架构设计

如果量不大的话,可以直接查询数据库/使用redis缓存。

select * from 帖子表 left join 帖子内容表 on 帖子.id = 帖子内容.帖子ID;

如果涉及查询、模糊匹配,可以考虑通过binlog的方式将 帖子内容同步到ES中,进行文本搜索。
在ES中冗余帖子标题、频道、标签、位置、内容等等。

(3)发帖子功能设计

总体流程:发帖子的时候,添加图片和视频,当点击确定的时候,视频和图片已经上传好了(异步上传),返回一个ID或者地址,只需要在数据库里存储这个地址即可。

细节处理:标签处理、文本和视频审核、处理表情、处理视频(添加水印等)。

2、帖子高性能架构设计

(1)上亿帖子分库分表

帖子上亿之后,分库分表其实并不是很好实现,不论是根据帖子ID分,还是根据用户ID分,其实对于一些功能都不是很友好。
比如说,有可能按照同城搜索、按照频道搜索、按照用户搜索等等。

或许考虑根据时间来进行分库分表,或许更加合理一些。

(2)redis缓存设计1:用户维度缓存(查询个人帖子列表)

查询“我的关注”功能,以用户维度进行缓存。

同一个用户一天发出的帖子数量是有限的,通常不超过10条,平均3条左右,单个用户一周发的帖子很难超过100KB,极端情况下1MB,远低于Redis value大小的上限。
所以考虑设计Redis:

key:userld+时间戳(精确到星期)
value:Redis为hash类型,field为postId,value为帖子内容
expire设置为一个星期,即最多同时存在两个星期的数据(假设每贴平均长度0.1KB,1亿用户每天发3贴预计数量为400GB)

对某个用户一段时间范围的查找变为针对该用户本周时间戳的hscan命令,用户发帖等操作同时更新DB和缓存,DB的变更操作记录保证一致性。

但是,有些热用户的粉丝数量极高,意味着这个热点用户所在Redis服务器的查询频率为1000万每秒,所以这里我们再进一步引入本地缓存来缓解服务端缓存压力。

(3)redis缓存设计2:时间维度缓存(参考Feed流)

查询“同城、频道”功能,以时间、置顶维度查询所有帖子。

先查询置顶的,剩余的按照发帖时间倒序排序,存入redis中(list格式)。
用户发帖,可以考虑DB和Redis双写,头插到缓存中,并更新过期时间。

可以考虑加上缓存淘汰策略,防止内存过高溢出。
也可以考虑使用滑动窗口的方式,动态删除和更新帖子的缓存。
也可以考虑添加热点探测功能,动态缓存热点帖子。

(4)帖子列表查询功能(用户维度/时间维度/频道维度)(参考Feed流)

1、查询预热,查询第一页的时候将下一页异步加载出来。
2、简略信息展示:文本过多展示…,视频和图片展示前三个,想要查看更多的话需要点击更多单独查看详情。

大致流程:
1、查询redis,list结构,key为用户id,value为帖子的json信息(id、标题、图片地址、内容等)。或者时间维度,key为时间或者频道ID。
2、根据帖子ID,查询帖子的点赞数、转发数等,进行数据拼装。
3、如果redis没查到,查询数据库并更新缓存。
4、用户拿到数据之后自行渲染,图片和视频的地址通过用户异步渲染即可。

redis缓存数据:
可以考虑缓存时间,比如缓存2周以内的帖子。
也可以考虑缓存的数据条数,比如100条,按照时间进行顶替。
冷门数据查询mysql即可,不需要进行缓存。

(5)帖子详情查看

根据帖子的ID,将帖子信息缓存到redis中。
考虑到部分热贴redis扛不住,可以考虑本地缓存。

3、Feed流架构设计

(1)Feed流简介

Feed:Feed流中的每⼀条状态或者消息都是Feed,⽐如朋友圈中的⼀个状态就是⼀个Feed,微博中的⼀条微博就是⼀个Feed。
Feed流:持续更新并呈现给⽤户内容的信息流。每个⼈的朋友圈,微博关注⻚等等都是⼀个Feed流。

Timeline:按照时间的Feed流,Timeline其实是⼀种Feed流的类型,微博,朋友圈都是Timeline类型的Feed流,但是由于Timeline类型出现最早,使⽤最⼴泛,最为⼈熟知,有时候也⽤Timeline来表示Feed流。
关注⻚Timeline:展示其他⼈Feed消息的⻚⾯,⽐如朋友圈,微博的⾸⻚等。
个⼈⻚Timeline:展示⾃⼰发送过的Feed消息的⻚⾯,⽐如微信中的相册,微博的个⼈⻚等。

Feed流系统最⼤的特点:
读写严重不平衡,读多写少,⼀般读写⽐例都在10:1,甚⾄100:1之上。

随着⽤户关系的变化,某个⽤户的timeline也随之变化。⽽⼀个⽤户对⾃⼰帖⼦的增删,会影响多个其他⽤户的timeline。
可⻅timeline的内容受⽤户间关系影响,当用户关系复杂时,timeline的性能将会受到挑战。

(2)pull模式

和push模式不同,pull模式下⽤户每次新增/删除不需要同步帖子数据到他的所有follower,所以不存在push模式下热点⽤户增删帖⼦瓶颈。
但是每个⽤户查询我关注的帖子时,需要同时查询其所有的关注的⽤户近期帖⼦列表,查询压力比较大。

-- 查询我的关注(如果分库分表的话,查询比较麻烦)
-- 不需要timeline表了,直接查投递箱即可,或者直接查帖子表即可
select * from post where userid in (1, 2, 3) order by time limit 1, 10;

在这里插入图片描述
小型的系统,使用pull就可以了。

(3)push模式(对查询进行优化)

push模式的特点是:⽤户每次新增⼀条帖⼦,将此帖⼦推到他的follower所在DB分⽚上,follower在每次浏览timeline时,直接查询⾃⼰分⽚所存储的数据。

timeline表结构:
ID、用户ID(关注者ID)、帖子ID、帖子时间

比如说,用户1有2、3、4三个粉丝,用户1发布了一个帖子(ID为99)以后,在timeline中记录四条记录(自己本身也需要记录一条):

ID、用户ID(关注者ID)、帖子ID、帖子时间
1	1	99	20252	2	99	20253	3	99	20254	4	99	2025

分库分表的话,根据用户ID分库分表即可。

优点:查询比较方便:

select * from timeline where userid = 2;

缺点:
1、如果粉丝比较多的话,需要一次性在数据库中新增很多数据,造成增删帖⼦瓶颈。
2、除了发帖以外,删帖、关注、取关操作,同样需要操作timeline表数据。

(4)push和pull模式优化

push优化:
设置上限(微信好友的上限,qq好友的上限,小红书、微博关注上限)

pull优化:
增加轮询间隔,减少请求次数
主动刷新多次增加验证码等限制

push和pull结合:
1、可以对⼤V采⽤pull(拉)模式,普通⽤户使⽤push(推)模式。大V粉丝多,普通用户粉丝少。
2、对活跃粉丝采⽤推模式,⾮活跃粉丝采⽤拉模式(这种⽅式可以较好的避免⼤流量对平台的冲击)

(5)发帖、读贴流程及缓存架构设计

缓存设计两个箱子:
收件箱(inbox)(redis):存放发送过来的帖⼦id
发件箱(outbox)(redis):存放⽤户⾃⼰发的帖⼦id(相当于是个⼈的timeline)
缓存使⽤Redis的zset进⾏存储,key是接收者uid,value是postid,按照时间排序。(相当于缓存了收件箱)

发送Feed流程:⽤户发帖,发送这个feed我们是需要使⽤MQ的
1、Feed消息先进⼊⼀个队列服务。
2、先从关注列表中读取到⾃⼰的粉丝列表,以及判断⾃⼰是否是⼤V。
3、将⾃⼰的Feed消息写⼊个⼈⻚Timeline(发件箱)。
4、如果是⼤V,此时拉取活跃⽤户;如果是普通⽤户,则拉取⾃⼰的所有粉丝⽤户(活跃和⾮活跃⽤户)。然后将⾃⼰的Feed消息同步写给⾃⼰的粉丝,同步的内容为Feed ID。(大V的活跃粉丝用push,大V的非活跃粉丝用pull,普通用户都用push,注意!自己也是自己的粉丝
5、发布Feed的流程到此结束。
在这里插入图片描述在这里插入图片描述

读取Feed流程:
1、判断⾃⼰是否是活跃⽤户,如果不是,去读取⾃⼰关注的⼤V列表。如果是活跃用户,只需要查看自己收件箱即可
2、读取⾃⼰的收件箱,范围起始位置是上次读取到的最新Feed的ID,结束位置可以使当前时间,也可以是MAX。然后通过查询出来的FeedId反查Feed内容,并且把已经软删除的数据剔除出去。
3、非活跃用户如果有拉取到关注的⼤V列表,则再次并发读取每⼀个⼤V的发件箱,如果关注了10个⼤V,那么则需要10次访问。
4、非活跃用户合并2和3步的结果,然后按时间排序,返回给⽤户。

在这里插入图片描述

关注、取关,其实就是发帖与删帖的流程。

四、附近的人架构设计

陌陌,探探这些社交软件附近的⼈特点:
可以进⾏数据筛选(男⼥,年龄等)
可以进⾏排序
对距离精准度计算要求相对⾼

微博、小红书、抖⾳附近的⼈特点:
实际上查询的是附近的帖⼦
对距离精准度计算要求相对不⾼
不需要进⾏数据筛选(男⼥,年龄等)

1、架构设计

使用mysql+redis的geohash数据结构实现即可。

用户登录、用户发帖记录经纬度值,存入mysql和redis。
用户点击附近的人,通过自身的经纬度以及帖子或者其他人的经纬度,判断距离进行筛选。

数据多的话,用redis按照地区进行分库分表即可。

五、评论服务架构设计

1、什么是评论系统

评论只分为两级,显示总评论数、每个评论的点赞数、评论者、被评论者。

评论系统都包含什么内容:
1.发表评论:⽀持⽆限盖楼回复
2.读取评论:按照时间,热度排序;显示评论数,楼中楼等
3.删除评论:⽤户删除,作者删除,后台管理员删除
4.评论互动:点赞,举报等
5.管理评论:置顶,精选,后台运维管理(搜索,删除,审核等)
6.富⽂本展示:例如表情分享等。
7.评论标签:例如作者点赞,作者回复,好友点赞等
8.评论装扮:⼀般⽐较热的评论会出现好评,神评等装饰
9.热评管理:结合AI和⼈⼯,为⽤户营造更好的评论区氛围。
在这里插入图片描述

2、评论系统基本功能设计

(1)数据库设计与选型

comment评论表:
ID、objId(对象ID,比如帖子、视频、留言等)、
type(类型,帖子、视频、商品)、
memberId(发表者)、
root(根ID,不为0则是回复评论,用于查询回复链)、parent(父评论ID,0为root评论)、
floor(评论楼层)、like(点赞数)、
status(状态,正常/隐藏)、top(置顶)、
message(评论内容)、count(评论总数,展开***条回复,查看子评论数量)、time(时间)

评论业务的数据是海量的,数据量随着业务⽅的增多成倍增⻓,需要具备快速便捷的⽔平扩展和迁移能⼒。
评论业务需要提供快速和稳定的读写能⼒,能够读写分离和⾃动恢复。
⽽评论业务不涉及⽤户资产,对事务的要求性不⾼。因此选⽤ MongoDB 集群 作为最底层的数据存储⽅式。

中小型的系统,用mysql就可以了,如果是大型系统,可以考虑MongoDB有更大的优势。

(2)基本功能实现

此处提供mysql实现方式,mongodb同理。

1、发评论功能
需要校验文本审核、黑名单校验,然后入库。
如果是二级评论,需要修改父评论的子评论总数+1。

-- 2、查询所有评论,需要进行分页查询
select * from comment where objId=1 and parent = 0 order by time desc;

3、高性能评论系统架构设计

(1)基于mysql+redis缓存架构设计

在这里插入图片描述
因为不是使⽤MongoDB存储数据,使⽤MySQL存储数据,所以关联查询是⽐较⽅便的,所以这⾥我们可以创建三张表
计数表:包含id主键,根+⼦评论总数,根评论总数等
索引表:id主键,发表者id,跟评论id,⽗评论id等,和MongoDB其实是⼀样的
内容表:内容的大小是不确定的,考虑单独使用一张表。

缓存设计:
1、计数缓存(点赞数、评论数)
2、评论id列表(index):zset类型,根据时间或热度排序
3、根评论(key:作者id;value:根评论id列表),查看评论列表时,默认只展示根评论列表。
4、⼆级评论(key:根评论id;value:⼆级评论id列表)
5、评论的具体内容 string类型, key:评论id value:评论内容
可以按照时间或者点赞数进⾏排序(根评论根据点赞数进⾏排序,⼦评论是根据时间来进⾏排序)(基于zset类型,分数为时间或者点赞数

本地缓存:
缓存热门帖子的热门评论的前几条点赞数最多的评论和二级评论。(通过热点探测技术)

新增、删除评论:
需要同步删除缓存,或者监听binlog重建缓存。

(2)分库分表或者使用NewSQL

根据objId(对象ID)进行分库分表。

数据量大的话,可以考虑使用MongoDB或者NewSql数据库TiDB、HBase等。

(3)高性能判断是否给评论点赞

在这里插入图片描述

创建⼀张表来记录所有的数据,然后再把这些数据保存在缓存当中,通过读取缓存来判断⽤户是否点赞过。
数据量是非常庞大的。
使用bitmap的话,问题也很多的,稀疏数据也会浪费大量的空间。

可以考虑使用布隆过滤器。(注意,布隆过滤器查不到的话是一定没有,查到的话不一定有,需要进行二次查询。而且布隆过滤器不允许删除,所以需要添加一个取消点赞的缓存)
可以考虑点赞数少的话(<1000),直接用redis的set,如果大于1000,就使用布隆过滤器,顺便初始化。
在这里插入图片描述

六、签到服务架构设计

1、基本功能设计

⽤户签到功能,一般会送代金券、积分等等。

user_integral用户积分表:
ID、userId、当前积分。

user_integral_log用户积分流水表:
ID、userId、type(积分类型 1.签到 2.连续签到 3.补签)、integral(积分)、operation_time(操作时间,签到和补签的具体⽇期)

用Redis的bitmap,⽤来实现签到是恰到好处的,可以对用户按照每天进行bitmap的记录。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2391655.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

RISC-V PMA、PMP机制深入分析

1 PMA PMA&#xff08;Physical Memory Attributes&#xff09;&#xff0c;物理内存属性&#xff0c;顾名思义就是用来设置物理内存属性的&#xff0c;但这里说“设置”&#xff0c;并不合理&#xff0c;因为一般情况下各存储的属性&#xff0c;在芯片设计时就固定了&#xf…

【NebulaGraph】查询案例(七)

【NebulaGraph】查询案例 七 1. 查询语句12. 查询语句23. 查询语句34. 查询语句4 1. 查询语句1 GO FROM "player100" OVER * YIELD type(edge) AS link, properties($$) AS properties,tostring(src(edge)) AS src,tostring(dst(edge)) AS dst, tags($$) AS tagLi…

从“刚性扩容”到“弹性供给”:移动充电服务重构配电网边际成本

随着新能源技术的快速发展&#xff0c;电动汽车的普及对传统配电网提出了新的挑战。传统的“刚性扩容”模式依赖基础设施的物理扩建&#xff0c;不仅投资成本高&#xff0c;且难以应对动态变化的电力需求。在此背景下&#xff0c;“弹性供给”理念逐渐兴起&#xff0c;特别是移…

Grafana-Gauge仪表盘

仪表盘是一种单值可视化。 可让您快速直观地查看某个值落在定义的或计算出的最小和最大范围内的位置。 通过重复选项&#xff0c;您可以显示多个仪表盘&#xff0c;每个对应不同的序列、列或行。 支持的数据格式 单值 数据集中只有一个值&#xff0c;会生成一个显示数值的…

游戏引擎学习第313天:回到 Z 层级的工作

回顾并为今天的内容定下基调 昨天我们新增了每个元素级别的排序功能&#xff0c;并且采用了一种我们认为挺有意思的方法。原本计划采用一个更复杂的实现方式&#xff0c;但在中途实现的过程中&#xff0c;突然意识到其实有个更简单的做法&#xff0c;于是我们就改用了这个简单…

Milvus部署架构选择和Docker部署实战指南

导读&#xff1a;向量数据库作为AI时代的核心基础设施&#xff0c;Milvus凭借其强大的性能和灵活的架构设计在市场中占据重要地位。然而&#xff0c;许多开发者在部署Milvus时面临架构选择困惑和配置复杂性挑战&#xff0c;导致项目进展受阻。 本文将为您提供一套完整的Milvus部…

高效合并 Excel 表格实用工具

软件介绍 这里介绍一款用于 Excel 合并的软件。 使用反馈与工具引入 之前推荐过 Excel 合并工具&#xff0c;但有小伙伴反馈这些工具对于需要合并单元格的 Excel 文件不太适用&#xff0c;而且无法合并表头。鉴于这些问题&#xff0c;找到了今天要介绍的这款 Excel 合并工具…

拉取gitlab项目

一、下载nvm管理node 先下载配置好nvm,再用nvm下载node 下载链接&#xff1a;开始 下载nvm - nvm中文官网 情况&#xff1a;npm i 下载依赖缓慢&#xff0c;可能是node版本不对&#xff0c;可能node版本太高 可能得问题&#xff1a;使用nvm 下载低版本的node时&#xff0c;…

树莓派(Raspberry Pi)安装Docker教程

本章教程,主要介绍如何在树莓派上安装Docker。 一、安装步骤 # 卸载旧版本(如果有): for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt-get remove $pkg;

计算机视觉---YOLOv4

YOLOv4&#xff08;You Only Look Once v4&#xff09;于2020年由Alexey Bochkovskiy等人提出&#xff0c;是YOLO系列的重要里程碑。它在YOLOv3的基础上整合了当时最先进的计算机视觉技术&#xff0c;实现了检测速度与精度的显著提升。以下从主干网络、颈部网络、头部检测、训练…

在雄性小鼠自发脑网络中定位记忆巩固的因果中枢

目录 简要总结 摘要 1 引言 2 方法 3 结果 简要总结 这篇文章主要研究了雄性小鼠在自发脑网络中记忆巩固的因果中枢定位。记忆巩固涉及学习后休息和睡眠期间全脑网络的自发重组&#xff0c;但具体机制尚不清楚。目前理论认为海马体在这一过程中至关重要&#xff0c;但其他…

刷机维修进阶教程-----没有开启usb调试 如何在锁定机型的拨号界面特殊手段来开启ADB

有时候我们会遇到一些机型被屏幕锁 账号锁等锁定。无法进入系统界面。也没有开启usb调试的情况下如何通过一些操作来开启adb调试。然后通过adb指令来禁用对应的app顺利进入系统。以此来操作保数据等操作. 通过博文了解💝💝💝 1💝💝💝----了解一些品牌机型锁定状态…

Selenium 测试框架 - Kotlin

🚀Selenium Kotlin 实践指南:以百度搜索为例的完整测试示例 随着测试自动化的普及,Selenium 已成为 Web 自动化测试的事实标准,而 Kotlin 凭借其简洁语法和高安全性,越来越受到开发者欢迎。本指南将通过一个完整的实战案例——在百度中执行搜索操作,来展示如何使用 Sele…

010501上传下载_反弹shell-渗透命令-基础入门-网络安全

文章目录 1 上传下载2 反弹shell命令1. 正向连接&#xff08;Forward Connection&#xff09;正向连接示例&#xff08;nc&#xff09; 2. 反向连接&#xff08;Reverse Connection&#xff09;反向连接示例&#xff08;反弹 Shell&#xff09; 对比表格实际应用中的选择防御建…

Flask集成Selenium实现网页截图

先看效果 程序实现的功能为&#xff1a;截取目标网址对应的页面&#xff0c;并将截取后的页面图片返回到用户端&#xff0c;用户可自由保存该截图。 支持的url参数如下&#xff1a; url&#xff1a;目标网址&#xff08;必填项&#xff09;&#xff0c;字符串类型&#xff0c…

知识图谱:AI时代语义认知的底层重构逻辑

在生成式人工智能&#xff08;GEO&#xff09;的技术架构中&#xff0c;知识图谱已从辅助性工具演变为驱动机器认知的核心神经中枢。它通过结构化语义网络的重构&#xff0c;正在突破传统数据处理的线性逻辑&#xff0c;建立机器对复杂业务场景的深度理解能力。 一、语义解构&a…

QGIS新手教程2:线图层与多边形图层基础操作指南(点线互转、中心点提取与WKT导出)

QGIS新手教程&#xff1a;线图层与多边形图层基础操作指南&#xff08;点线互转、中心点提取与WKT导出&#xff09; 目录 QGIS新手教程&#xff1a;线图层与多边形图层基础操作指南&#xff08;点线互转、中心点提取与WKT导出&#xff09;&#x1f4cc; 引言第一部分&#xff1…

Windows环境下Redis的安装使用与报错解决

最近在做项目的时候需要用到Redis&#xff0c;本来没觉得是什么麻烦&#xff0c;下载安装使用一步到位的事&#xff0c;但紧随而来的问题&#xff0c;让我开始怀疑人生&#xff0c;再加上代码跑不出来&#xff0c;我还专门找人给我看看怎么个是&#xff0c;结果就是单纯的Redis…

鸿蒙完整项目-仿盒马App(一)首页静态页面

跟着鸿蒙小林博主&#xff0c;练习下项目~记录下首页的搭建,后续继续完善和整体项目完成会进行布局修改&#xff0c;先按照博主的跟做&#xff0c;后续在改 1.分为底部整体框架搭建 2.首页布局&#xff08;顶部搜索、新人专享、金刚区&#xff08;两个不同集合数据&#xff09…

39-居住证管理系统(小程序)

技术栈: springBootVueMysqlUni-app 功能点: 群众端 警方端 管理员端 群众端: 1.首页: 轮播图展示、公告信息列表 2.公告栏: 公告查看及评论 3.我的: 联系我们: 可在线咨询管理员问题 实时回复 居住证登记申请 回执单查看 领证信息查看 4.个人中心: 个人信息查看及修改…