东莞网站建设 石佳,jsp网站建设项目实战总结,灵璧哪有做网站的,网站推广网站策划说在前面
在尼恩的#xff08;50#xff09;读者社群中#xff0c;经常遇到一个 非常、非常高频的一个面试题#xff0c;但是很不好回答#xff0c;类似如下#xff1a; 千万级数据#xff0c;如何做系统架构#xff1f;亿级数据#xff0c;如何做系统架构#xff1…说在前面
在尼恩的50读者社群中经常遇到一个 非常、非常高频的一个面试题但是很不好回答类似如下 千万级数据如何做系统架构亿级数据如何做系统架构千万级流量如何做系统架构亿级流量如何做系统架构高并发系统如何架构 最近有个尼恩的社群中有小伙伴阿里三面又遇到了这个问题。
其实尼恩一直想梳理一个教科书式的答案
咱们一直心心念念的 “千万级数据如何做性能优化” 的教科书式的答案其实就藏着在这个行业案例里边。
前几天尼恩结合B站的点赞系统写过一个 教科书式的答案
1000亿数据、30W级qps如何架构来一个天花板案例
这里再结合一个新的行业案例《B站评论系统架构设计》尼恩从 面试维度对这个方案进行二次重构和梳理现在写一个 教科书式的答案并收入咱们的《尼恩Java面试宝典 PDF》 V58版本
统一都做了解答这些答案都可以给后面的小伙伴参考大家一定好好看看这些教科书级别的答案。
本文原始方案的作者是黄振是哔哩哔哩资深开发工程师。
此文的原始文章请参见b站的公众号 pdf版收藏在尼恩的3高行业案例集合中也可以找尼恩获取。 本文的架构方案是尼恩在作者的B站方案的二次创作是结合自己的3高架构笔记以及尼恩的3高架构知识体系3高架构宇宙做的二次分析。 文章中加入了社群小伙伴遇到的最新面试题 redis 集群如何做同城双活 参考答案见下文。 注本文以 PDF 持续更新最新尼恩 架构笔记、面试题 的PDF文件请从这里获取码云 评论系统的业务分析
在B站UP主每天都会发布海量的视频、动态、专栏等内容随之而来的是弹幕和评论区的各种讨论。
播放器中直接滚动播放的弹幕如同调味剂重在提升视频观看体验
而点进评论区相对而言评论文本更长内容的观点、形式都更丰富更像是饭后甜点。
随着业务不断发展B站的评论系统逐渐组件化、平台化
通过持续演进架构设计管理不断上升的系统复杂度从而更好地满足各类用户的需求。
评论的基础功能模块是相对稳定的。
发布评论支持无限盖楼回复。读取评论按照时间、热度排序显示评论数、楼中楼等。删除评论用户删除、UP主删除等。评论互动点赞、点踩、举报等。管理评论置顶、精选、后台运营管理搜索、删除、审核等。
结合B站以及其他互联网平台的评论产品特点评论一般还包括一些更高阶的基础功能
评论富文本展示例如表情、、分享链接、广告等。评论标签例如UP主点赞、UP主回复、好友点赞等。评论装扮一般用于凸显发评人的身份等。热评管理结合AI和人工为用户营造更好的评论区氛围。
总体的架构设计
评论系统 中台从总体的架构上来区分分为
1接入层
2服务层
3异步任务层
4cache层
5DB层 接入层架构 reply-interface
reply-interface是评论系统的接入层主要服务于两种调用者
一是客户端的评论组件
二是基于评论系统做二次开发或存在业务关联的其他业务后端。
面向移动端/WEB场景设计一套基于视图模型的API利用客户端提供的布局能力接入层负责组织业务数据模型并转换为视图模型编排后下发给客户端。
面向服务端场景接入层设计的API需要体现清晰的系统边界最小可用原则对外提供数据同时做好安全校验和流量控制。 接入层整个业务数据模型组装分为两个步骤
一是服务编排,
二是数据组装。
服务编排拆的架构为
1对服务进行分层分为若干个层级
2前置依赖通过流水线调用
3同一层级的可以并发调用结构性提升了复杂调用场景下的接口性能下限
4针对不同依赖服务所提供的SLA不同设置不同的降级处理、超时控制和服务限流方案保证少数弱依赖抖动甚至完全不可用情况下评论服务可用。
SLA一般指服务级别协议。 服务级别协议是指提供服务的企业与客户之间就服务的品质、水准、性能等方面所达成的双方共同认可的协议或契约。
服务层架构
评论管理服务层reply-admin
评论管理服务层为多个内部管理后台提供服务。
运营人员的数据查询具有
组合、关联查询条件复杂刚需关键词检索能力写后读的可靠性与实时性要求高等特征。
此类查询需求ES几乎是不二选择。
但是由于业务数据量较大需要为多个不同的查询场景建立多种索引分片且数据更新实时性不高。
因此我们基于ES做了一层封装提供统一化的数据检索能力并结合在线数据库刷新部分实时性要求较高的字段。 评论基础服务 reply-service 架构设计
评论基础服务层专注于评论功能的原子功能例如
查询评论列表删除评论等。
这一层的特点是
较少做业务逻辑变更的极高的可用性极高性能吞吐。
这一层采用了多种高性能方案
多级缓存布隆过滤器热点探测等。 尼恩提示 多级缓存、布隆过滤器、热点探测等理论和实操非常重要 很多的高并发应用都要用到这些理论知识和实操知识大家一定 要掌握 具体可以参见尼恩的3高架构知识笔记。 异步任务层reply-job 架构设计
异步任务层主要有两个职责
为原子的业务操作操作提供异步协助
与reply-service协同为评论基础功能的原子化实现做架构上的补充。
异步削峰处理
为 长耗时/高吞吐的调用, 做异步化/削峰处理
职责1提供异步协助
为原子的业务操作操作提供异步协助 最典型的案例就是缓存的更新。
一般采用Cache Aside模式先读缓存再读DB
Cache Aside模式下的缓存的重建策略就是读请求未命中缓存穿透到DB从DB读取到内容之后反写缓存。
这一套流程对外提供了一个原子化的数据读取功能。
但由于部分缓存数据项的重建代价较高比如评论列表。
为啥呢
由于列表是分页的缓存重建时会启用预加载也就是要多加载几页
如果短时间内大量请求缓存未命中并且多个服务节点的同时重建缓存容易造成DB抖动。
解决方案是啥
利用消息队列reply-job 实现单个评论列表异步重建只重建一次缓存。
另外呢reply-job还作为数据库binlog的消费者执行缓存的更新操作。 职责2异步削峰处理
与reply-interface协同为 长耗时/高吞吐的调用做异步化/削峰处理
诸如评论发布等操作基于安全/策略考量会有非常重的前置调用逻辑。
对于用户来说这个长耗时几乎是不可接受的。同时时事热点容易造成发评论的瞬间峰值流量。
因此reply-interface在处理完一些必要校验逻辑之后会通过消息队列送至reply-job异步处理包括送审、写DB、发通知等。
那么异步处理后用户体验是如何保证的呢
首先是当次交互返回最新数据。
C端的发评接口会返回展示新评论所需的数据内容客户端据此展示新评论完成一次用户交互。
其次控制延迟时长如果太长则进行预警和调优
若用户重新刷新页面因为发评的异步处理端到端延迟基本在2s以内此时所有数据已准备好不会影响用户体验。
消息队列的保证有序
利用了消息队列的「有序」特性将单个评论区内的发评串行处理避免了并行处理导致的一些数据错乱风险。
一个有趣的问题是早年间评论显示楼层号楼层号实际是计数器且在一个评论区范围内不能出现重复。
因此这个楼层发号操作必须是在一个评论区范围内串行的或者用更复杂的锁实现否则两条同时发布的评论获取的楼层号就是重复的。
而分布式部署负载均衡的网关处理发评论请求是无法实现这种串行的因此需要放到消息队列中处理。
数据存储架构
结构化模型设计
结合评论的产品功能要求评论需要至少两张表
1首先是评论表主键是评论id关键索引是评论区id
2其次是评论区表主键是评论区id平台化之后增加一个评论区type字段与评论区id组成一个”联合主键“。
3评论内容表. 由于评论内容是大字段且相对独立、很少修改因此独立设计第3张表。主键也是评论id。
评论表和评论区表的字段主要包括4种
关系类包括发布人、父评论等这些关系型数据是发布时已经确定的基本不会修改。计数类包括总评论数、根评论数、子评论数等一般会在有评论发布或者删除时修改。状态类包括评论/评论区状态、评论/评论区属性等评论/评论区状态是一个枚举值描述的是正常、审核、删除等可见性状态评论/评论区属性是一个整型的bitmap可用于描述评论/评论区的一些关键属性例如UP主点赞等。其他包括meta等可用于存储一些关键的附属信息。
评论回复的树形关系如下图所示 以评论列表的访问为例我们的查询SQL可能是已简化
查询评论区基础信息SELECT * FROM subject WHERE obj_id? AND obj_type?查询时间序一级评论列表SELECT id FROM reply_index WHERE obj_id? AND obj_type? AND root0 AND state0 ORDER BY floor? LIMIT 0,20批量查询根评论基础信息SELECT * FROM reply_index,reply_content WHERE rpid in (?,?,…)并发查询楼中楼评论列表SELECT id FROM reply_index WHERE obj_id? AND obj_type? AND root? ORDER BY like_count LIMIT 0,3批量查询楼中楼评论基础信息SELECT * FROM reply_index,reply_content WHERE rpid in (?,?,…)
分库分表架构
评论系统对数据库的选型要求有两个基本且重要的特征
必须有事务必须容量大。
一开始B站采用的是MySQL分表来满足这两个需求。MySQL分库分表数据量起来之后原来的MySQL分表架构很快到达存储瓶颈。 尼恩提示 mysql 不停服在线扩容实际非常复杂很多公司选择停服切换 估计B站为了不停服 或者不愿意发生停服的风险 选择了 专门的商用 分布式 TiDB 毕竟这个是花了钱的。 于是从2020年起我们逐步迁移到TiDB从而具备了在线水平扩容能力。
高并发写入架构TPS提升了10倍以上
面对10Wqps的并发写入超大规模吞吐量做了如下优化
方案一内存聚合 批量写入 评论区评论计数的更新先做内存合并再更新可以减少热点场景下的SQL执行条数评论表的插入改成批量写入。 tips 这就是 尼恩3高架构知识宇宙当中所讲的 队列缓存批量写入的架构 具体请去看 100Wqps 三级缓存组件实操 方案二核心逻辑和非核心异步化为核心操作瘦身
非数据库写操作的其他业务逻辑拆分为前置和后置两部分
其他业务逻辑从数据写入主线程中剥离交由其他的线程池并发执行。
总之采用新的高并发写入架构之后性能得到极大提升。
写入架构调整之后系统的并发处理能力有了极大提升同时支持配置并行度/聚合粒度在吞吐方面具备更大的弹性热点评论区发评论的TPS提升了10倍以上。 缓存层架构
数据的缓存模型架构
主要有3项缓存
subject对应于「查询评论区基础信息」 redis string类型value使用JSON序列化方式存入。reply_index对应于「查询xxx评论列表」 redis sorted set类型。 member是评论idscore对应于ORDER BY的字段如floor、like_count等。reply_content对应于「查询xxx评论基础信息」 存储内容包括同一个评论id对应的reply_index和reply_content表的两部分字段。
缓存的一致性架构
缓存的一致性依赖binlog刷新主要两个要点
消息队列保证 同一个评论区内有序
binlog投递到消息队列分片key选择的是评论区保证单个评论区和单个评论的更新操作是串行的消费者顺序执行保证对同一个member的zadd和zrem操作不会顺序错乱。
采用删除缓存而非直接更新的方式
程序主动写缓存和binlog刷缓存都采用删除缓存而非直接更新的方式避免并发写操作时特别是诸如binlog延迟、网络抖动等异常场景下的数据错乱。
缓存击穿解决方案
那大量写操作后读操作缓存命中率低的问题如何解决呢
读缓存的时候 可以利用 锁的机制进行同步控制防止缓存击穿。
具体方案请参见尼恩的3高架构笔记中redis 高可用实操的章节
热点探测架构
除了写热点评论的读热点也有一些典型的特征
由于大量接口都需要读取评论区基础信息存在读放大因此该操作是最先感知到读热点存在的。由于评论业务的下游依赖较多且多是批量查询对下游来说也是读放大。此外很多依赖是体量相对小的业务单元数据稀疏难以承载评论的大流量。评论的读热点集中在评论列表的第一页以及热评的热评。评论列表的业务数据模型也包含部分个性化信息。
在读取评论区基础信息阶段探测热点并将热点标识传递至服务层
服务层实现了页面请求级的热点本地缓存感知到热点后即读取本地缓存然后再加载个性化信息。 热点探测的实现基于单机的滑动窗口LFU那么如何定义、计算相应的热点条件阈值呢
首先我们进行系统容量设计列出容量计算的数学公式主要包括各接口QPS的关系、服务集群总QPS与节点数的关系、接口QPS与CPU/网络吞吐的关系等
然后收集系统内部以及相应依赖方的一些的热点相关统计信息通过公式计算出探测数据项的单机QPS热点阈值。
最后通过热点压测来验证相应的热点配置与代码实现是符合预期的。
高可用架构
包括
1缓存降级与DB降级
2同城读双活 双机房独立部署 架构
3副本数据延迟优化架构
4限流熔断策略的优化
缓存降级与DB降级
基础服务层集成了多级缓存在上一级缓存未命中或者出现网络错误后降级至下一级缓存
缓存没有命中就降级到DB保证系统的的可用性。 同城读双活 双机房独立部署 架构
评论系统是一个同城读双活 双机房独立部署 的架构。
DB 和 redis 均支持多副本具备水平扩容的弹性。
双机房独立部署 :
数据库与缓存均是双机房独立部署的通过 db-proxy或者 db-redis进行访问 副本数据延迟优化架构
双机房架构场景下存在跨机房数据延迟问题
采用如下的策略解决
入口层切流应用层补偿跨机房重试
尽可能保证极端情况下, 用户没有延迟感。 限流熔断策略的优化
为了尽可能 保证系统可用 在功能层面做了级别划分 把依赖划分为强依赖如审核、弱依赖如粉丝勋章。 首先在如果强依赖出现异常下坚决限流熔断尽可能 保证 强依赖的可用性。
另外对于弱依赖通过超时控制、请求预过滤、优化调用编排 持续优化提升非核心功能的可用性 重点Redis 的双机房部署方案
tips在写这个文章的过程中尼恩的疯狂创客圈社群中有小伙伴说他刚刚面试遇到了一道难题 双机房部署redis该怎么做 ? 顺着这个文章尼恩 给大家 把双机房部署redis 方案说一下。
采用 redis-cluster-proxy redis cluster的架构方案。
redis cluster是redis的官方集群方案但是他要求客户端自己做重定向
redis-cluster-proxy 是redis的官方集群代理经过这个proxy的代理后连接redis集群就和连接单机redis一样了。 proxycluster架构
proxycluster架构图如下 架构说明
1、redis-cluster采用了同城双活架构
其中图中的AZ1和AZ2表示为可用区1、可用区2
主节点AZ1按3主3从部署备节点AZ2作为Cluster的6从整个集群为3主9从
2、单个master节点发生故障redis集群自动感知并进行选主完成主从切换不影响业务正常使用
3、应用服务连接所有Redis集群主从节点以便自动感知主从切换情况。
其实只要连接到redis-proxy一个节点应用服务便可以获取到集群信息某些节点宕机后客户端不会收到影响。
注意单AZ1池资源出现问题可以使用已准备好的脚本进行快速切换AZ2节点完成集群恢复。
当然上面的方案可以考虑把master节点打散到两个AZ避免集群超半数master节点宕机
proxycluster架构问题
redis-proxy模式采用官方的redis-proxycluster模式优点就是应用只需要连接proxy节点即可不需要配置更多的node节点生产环境proxy需要考虑高可用而proxy也可以考虑用lvskeepalived作为代理取代
自动切换脚本
先使用cluster failover force命令执行强制切库如果试了3次都不行就使用cluster failover takeover更强制的切库
手动故障转移是一种特殊的故障转移通常在没有实际故障的情况下执行我们希望将当前主节点与其中一个slave从节点我们发送该命令的节点交换安全地而不会有数据丢失的窗口。 当前slave从节点通知主节点停止处理客户端的请求。主节点回复slave从节点当前的 同步偏移量。slave从节点等待同步偏移量在slave从节点的侧匹配以确保它已经处理了所有主节点的数据然后继续。slave从节点开始故障转移从主节点的大多数主节点获取新的配置纪元值epoch并广播新的配置。旧的主节点接收配置更新解除对客户端访问的阻止并开始回复重定向消息以便它们继续与新的主节点通信。 两个选项 FORCE option: manual failover when the master is down 当主节点停止时手动故障转移 如果选择FORCE选项slave从节点不会与master主节点进行协商master节点可能不可达而是直接尽快从上文的故障转移步骤中的第4步开始做故障转移。当主节点不可达时FORCE选项对于我们做手动故障转移非常有用。 TAKEOVER option: manual failover without cluster consensus 在集群数据不一致的场景下也要人工故障转移 TACKOVER选项实现了FORCE选项的所有实现但是无需集群一致性验证来进行故障转移。 如果需要故障转移在从节点上可以输入以下命令
redis-cli -p 7001 -c CLUSTER FAILOVER也可以结合linux上的定时器使用脚本配合使用
1探活脚本redis_check.sh
2切换脚本redis_task.sh
redis_check.sh脚本为检测redis节点是否存活
#!/bin/bash LOGDIR/root
BINDIR/data/redis/7001/bin/redis-cli
PASSWD123456
IPDIR172.16.0.8:7001 172.16.0.8:7002 172.16.0.8:7003 172.16.0.8:7004 172.16.0.8:7005 172.16.0.8:7006
DATEdate
LOGFILE${LOGDIR}/logs
ERROR_LOG${LOGDIR}/error.logscd ${LOGDIR}
if [ ! -d bak ] ; thenmkdir -p bak
fifor i in $IPDIR
doport${i#*:}ip${i%:*}ALIVE$BINDIR -h $ip -p $port PING#ALIVE$BINDIR -h $ip -p $port -a $PASSWD PINGif [ $ALIVE PONG ]; thenecho ${DATE} Success: redis-cli -h $ip -p $port PING $ALIVE $LOGFILE 21elseecho ${DATE} Failed:redis-cli -h $ip -p $port PING $ALIVE $ERROR_LOG 21fidone
redis_task.sh为AZ1节点宕机后执行脚本切换到AZ2节点
#!/bin/bashIPMASTER172.16.0.8:7001 172.16.0.8:7002 172.16.0.8:7003
BINDIR/data/redis/7001/bin/redis-cli
PASSWD123456
DATEdate
LOGDIR/root
LOGFILE${LOGDIR}/logs
ERROR_LOG${LOGDIR}/error.logsfor i in $IPMASTER
doport${i#*:}ip${i%:*}status$BINDIR -h $ip -p $port -c cluster failover takeover#status $BINDIR -h $ip -p $port -a $PASSWD -c cluster failover takeoverif [ $status OK ]; thenecho ${DATE} Success: $i 成功切换成master节点 $LOGFILE 21elseecho ${DATE} Failed: $i 切换master节点失败 $ERROR_LOG 21fidone机房故障的redis 故障转移过程
最开始cluster搭建方式如下图所示 在AZ1机房全部宕机后我们需要通过执行cluster failover takeover命令将AZ2机房切换为Master如下图所示 在AZ1机房恢复正常之后如下图所示 安全性架构
一、数据安全
满足数据安全法要求除了数据安全法所要求的以外评论系统的数据安全还包括「合规性要求」。
评论数据合规一方面是审核和风控另一方面对工程侧的要求主要是「状态一致性」。
例如有害评论被删除后在客户端不能展现也不能通过API等对外暴露。
这就对数据一致性包括缓存提出了较高要求。
在设计层面主要有两方面实践
数据读写阶段均考虑了一致性风险严格保证时序性。对各类数据写操作定义了优先级避免高优先级操作被低优先级操作覆盖例如审核删除的有害评论不能被其他普通运营人员/自动化策略放出。通过冗余校验避免风险数据外泄。 例如评论列表的露出读取sorted set中的id列表后还需要校验对应评论的状态是可见态才允许下发。
二、舆论安全
舆论安全问题更为泛化。
接口错误导致用户操作失败、关闭评论区、评论计数不准甚至新功能上线、用户不满意的评论被顶到热评前排等问题均可能引发舆情问题。
在系统设计层面我们主要通过几方面规避。
不对用户暴露用户无法处理和不值得处理的错误。 例如评论点赞点踩、某个数据项读取失败这一类的轻量级操作不值得用户重试此时告知用户操作失败也没有意义。系统可以考虑自行重试甚至直接忽略。优化产品功能及其技术实现例如评论计数、热评排序等。
热评设计架构
什么是热评
早期的热评实际就是按照评论点赞数降序。
后来衍生了更为复杂的热评 既包括类似「妙评」这种用户推荐、运营精选且带logo突出展示的产品形态 也包括各类热评排序算法且热评排序算法应用场景也不仅局限于评论主列表的热度序 还包括楼中楼外露子评论、动态外露评论等。 热评排序逻辑一般包括点赞数、回复数、内容相关、负反馈数、“时间衰退因子”、字数加权、用户等级加权等等。
咬文嚼字来说我们对「热」的理解大致分为几个阶段
阶段1 点赞高就代表热度高。→ 解决热评的有无问题阶段2 基于用户正负样本投票的加权平均高就代表热度高。→ 解决高赞高踩的负面热评问题阶段3短时间内点赞率高就代表热度高。→ 解决高赞永远高赞的马太效应阶段4 热评用户流量大社区影响也大。→ 追求用户价值平衡, 要权衡社会价值观引导、公司战略导向、商业利益、UP主与用户的「情绪」等。
阶段1 按照点赞绝对值排序
按照点赞绝对值排序即要实现ORDER BY like_count的分页排序。
点赞数是一个频繁更新的值MySQL特别是TiDB由于扫描行数约等于OFFSET因此在OFFSET较大时查询性能特别差很难找到一个完美的优化方案。
此外由于like_count的分布可能出现同一个值堆叠多个元素比如评论区所有的评论都没有赞
我们更多依赖redis的sorted set来执行分页查询这就要求 缓存命中率非常高。
阶段2 按照正负样本加权平均排序
按照正负样本加权平均的即Reddit威尔逊排序[6]
到这个阶段数据库已经无法实现这样复杂的ORDER BY热评开始几乎完全依赖sorted set这样的数据结构预先计算好排序分数并写入。
于是在架构设计上新增了feed-service和feed-job来支撑热评列表的读写。 Reddit最早成立于2005年两名创始人是史蒂夫·霍夫曼和阿里克西斯·奥哈尼安当时他们刚刚从弗吉尼亚大学毕业。他们的创业想法获得了美国知名创业孵化器Y Combinator的天使投资。
Reddit在美国的影响力非常大它的信息展示形式像论坛又像贴吧。是由不同版块下的帖子组成的交流平台用户可以选择对帖子点击“上涨”或“下沉”来决定帖子的排名顺序。
Reddit在2009年公开过自己如何用威尔逊区间(wilson interval)对评论排序的代码也开源过。
Wilson算法要点有两个
把“所有正负反馈中正反馈的比例”作为对评论质量的考核指标。 在Reddit的情况中正负反馈分别为点赞和反对。 简单来说就是 正为点赞, 负为反对对在冷启动过程中的评论即正负反馈总数很少做降权处理。 具体算法就是假设观测到的正反馈率符合真实正反馈率的正态分布求当前观测得到的正反馈率恰好位于95%置信上区间时的真实反馈率。
阶段3按照点赞率排序
按照点赞率排序需要实现点赞率的近实时计算。
点赞率点赞数/曝光数曝光的数据来源是客户端上报的展现日志量级非常大
可以说是一个写多读少的场景只有重算排序的时候才会读取曝光数。
阶段4 追求用户价值平衡
追求用户价值平衡需要处理各种细分场景下的差异化需求。
热评排序与feed排序很像但也有一点根本性差异 feed排序是个性化的每个人看到的都不相同 但评论排序往往不会如此激进一般来说会希望大家看到的评论排序都大致相同。 由于排序问题的解决方案是探索型的因此系统设计层面需要提供更多元、更易扩展的工程化能力 包括算法和策略的快速迭代、实验能力等 并提升整个热评模块的可观测水平监控完善、数据报表丰富、排序过程可解释等等。 在架构上新增了strategy-service和strategy-job来承担这部分策略探索型业务。
此外数据量级规模的增加也对系统的吞吐能力提出了更高要求
不管热评的算法如何变化一般来说热评列表都需要能够访问到全部评论且基本维持相同的热评排序逻辑。
在评论数过百万甚至千万的评论区热评排序的挑战点主要在于
大key问题 例如单个sorted set过大读写性能都受影响时间复杂度的基数可以认为都是O(logN)全量更新时还可能遇到redis pipeline的瓶颈。实时性放大存储压力 多样化的数据源对特征的导入与更新都提出了挑战需要支持较丰富的数据结构和尽可能高的写吞吐想象一下曝光数作为排序特征的变态要求
与推荐排序不同热评排序是全排序此时需要读取全部评论的全部特征查询压力也会非常大。
这一阶段我们仍然在持续优化在工程落地层面尽可能还原理想的排序算法设计保障用户的热评浏览体验。目前形成的系统架构总体如下图所示 图示的「评论策略层」负责建立一套热评调控体系化能力通过召回机制来实现想要的“balance“。
即先通过策略工程召回一批应该沉底的不良评论或者应该进前排的优秀评论然后在排序分计算阶段根据召回结果实现这样的效果。
这样做的好处是可以保留一套通用的底层排序算法然后通过迭代细分场景下的召回策略来实现差异化评论排序的平衡。
召回策略的工程设计按照分层设计的原则拆分为3个部分
因子机。 主要职责是维护策略所需的全部「因子」包括一些已有的在线/离线数据也包括为了策略迭代而需要新开发的流式的窗口聚合数据。 因子机的重难点是需要管理各种数据获取的拓扑关系以及通过缓存来保护下游数据提供方很难也不应该承受热评业务的巨大流量。 所有的因子可以构成一个有向无环图通过梳理依赖关系和推导计算实现并发提效、减少冗余。规则机。 实现了一套声明式规则语法可以直接引用因子机预定义的因子结合各种逻辑算子构成一个规则表达式。 规则机执行命中后会向下游传递预先声明的召回决策例如排序提权。召回处理中心。 这一层的职责就是接收规则机返回的各种决策并执行需要处理不同决策的优先级PK、不同规则的决策叠加作用、决策豁免等。
热评排序涉及的特征是多数据源的数据更新方式、更新频率、查询性能也天差万别。
因此我们针对数据源的特点做了多级缓存通过多级冗余与跨级合并提升了特征读取的稳定性与性能上限。
当然其中的数据实时性、一致性、可用性仍然处于一个动态权衡取舍的过程。
结合 B站的方案大家回到前面的面试题
千万级数据如何做系统架构亿级数据如何做做系统架构千万级流量如何做系统架构亿级流量如何做做系统架构高并发系统如何架构
以上的方案才是完美的答案才是“教科书式” 答案。
后续尼恩会给大家结合行业案例分析出更多更加劲爆的答案。
当然如果大家遇到这类高并发的面试难题可以找尼恩求助。
参考资料
B站原文
https://www.bilibili.com/read/cv20346888
redis 集群异地双活参考
https://blog.csdn.net/u012171444/article/details/127525169
推荐阅读
《响应式圣经10W字实现Spring响应式编程自由》
《Linux命令大全2W多字一次实现Linux自由》
《网络三张表ARP表, MAC表, 路由表实现你的网络自由》
《阿里一面谈一下你对DDD的理解2W字帮你实现DDD自由》
《4次迭代让我的 Client 优化 100倍泄漏一个 人人可用的极品方案》
《全链路异步让你的 SpringCloud 性能优化10倍》
《干翻 nio 王炸 io_uring 来了 图解史上最全》
《SpringCloudDubbo3 王炸 》
《阿里一面你做过哪些代码优化来一个人人可以用的极品案例》
《网易二面CPU狂飙900%该怎么处理》
《阿里二面千万级、亿级数据如何性能优化 教科书级 答案来了》
《峰值21WQps、亿级DAU小游戏《羊了个羊》是怎么架构的》
《场景题假设10W人突访你的系统如何做到不 雪崩》
《2个大厂 100亿级 超大流量 红包 架构方案》
《Nginx面试题史上最全 持续更新》
《K8S面试题史上最全 持续更新》
《操作系统面试题史上最全、持续更新》
《Docker面试题史上最全 持续更新》
《Springcloud gateway 底层原理、核心实战 (史上最全)》
《Flux、Mono、Reactor 实战史上最全》
《sentinel 史上最全》
《Nacos (史上最全)》
《TCP协议详解 (史上最全)》
《分库分表 Sharding-JDBC 底层原理、核心实战史上最全》
《clickhouse 超底层原理 高可用实操 史上最全》
《nacos高可用图解秒懂史上最全》
《队列之王 Disruptor 原理、架构、源码 一文穿透》
《环形队列、 条带环形队列 Striped-RingBuffer 史上最全》
《一文搞定SpringBoot、SLF4j、Log4j、Logback、Netty之间混乱关系史上最全》
《单例模式史上最全》
《红黑树 图解 秒懂 史上最全》
《分布式事务 秒懂》
《缓存之王Caffeine 源码、架构、原理史上最全10W字 超级长文》
《缓存之王Caffeine 的使用史上最全》
《Java Agent 探针、字节码增强 ByteBuddy史上最全》
《Docker原理图解秒懂史上最全》
《Redis分布式锁图解 - 秒懂 - 史上最全》
《Zookeeper 分布式锁 - 图解 - 秒懂》
《Zookeeper Curator 事件监听 - 10分钟看懂》
《Netty 粘包 拆包 | 史上最全解读》
《Netty 100万级高并发服务器配置》
《Springcloud 高并发 配置 一文全懂》