老王在街角开了家小卖部,烟酒零食一应俱全。起初街坊邻里随来随买,老王一个人记账、理货、结账,好不惬意。可随着小区入住率变高,排队的人从柜台排到了马路牙子,货架也总被抢空,老王开始失眠:这生意,怎么继续做大? 他请来咨询师阿智。阿智说:“老王,你的小卖部就是一台单机服务器。顾客多了、货品多了,单靠你一个人当然忙不过来。要变大,得设计一套能'长'的系统。” 于是,老王从一家小卖部,慢慢开出了连锁超市,又做起了电商、建起了云仓。这背后的每一道坎——开多少分店、货放哪、账怎么对、店倒了怎么办——正是特征存储规模化道路上会遇到的所有问题。 这篇文章,就借着老王的生意经,把特征存储扩展性设计拆开揉碎讲清楚:从扩展性指标、水平扩充分片、分区策略、缓存设计,到一致性保障、高可用架构、性能监控与存储分层。你会发现,AI 平台里那些“神秘”的分布式设计,原理无非是“把生意做大”的朴素智慧。
掌握扩展性设计,你就能从“会搭特征存储”进阶为“能设计承载千万级特征量级的平台架构”,这是数据工程师与 AI 架构师的核心竞争力。
可视化演示
动态演示特征存储扩展性设计原则的核心机制,通过采集/分析/决策/反馈四种模式展示关键概念与交互流程。
本节配有交互动效(进入视口后自动加载,约 3KB)。
特征存储扩展性设计原则:特征存储 特征存储扩展性的核心概念 在线与离线存储的分层扩展 核心机制可视化 特征存储扩展性设计原则整体架构与关键组件
扩展性概述
老王的柜台前排起了长长的队伍,他请来阿智诊断。阿智没急着喊“加人”,而是先问:客人平均停留多久?一天来几波人?哪个货架最容易堵?这些“诊断指标”,就是扩展性设计的起点。
在特征存储里,扩展性指的是系统面对数据量、请求量增长时仍能保持稳定性能的能力。与老王面临的问题一样,扩展性不是“多雇几个人”那么简单,而是先用量化指标定位瓶颈。行业里最常用的两个指标是 QPS(每秒查询数)和延迟:前者回答“系统每秒能服务多少请求”,后者回答“每个请求要等多久”。两者通过 Little's Law 关联:
搞清楚指标后,就能做瓶颈分析:先看是 QPS 不够(客流太大),还是延迟太高(结账太慢),再对症下药。老王恍然大悟:他的问题是客流暴涨导致延迟飙升,属于典型的“需要扩展”的信号。而触发扩展的场景,往往是数据量翻倍、业务线激增或大促峰值——特征存储中同样如此:新的推荐场景上线、日活用户翻倍、模型迭代频率加快,都会把存储系统推向扩展的临界点。
- 并发量 C系统同一时刻在处理的请求数量,等价于店里同时被服务的顾客数。
- 平均响应时间 \overline{T}单个请求从发出到返回的平均耗时,等价于顾客从进店到结账离开的时间。
- 吞吐 QPS两者相除得到每秒吞吐量,公式整体表达“并发越高、响应越快,吞吐越大”。
水平扩展
老王决定开分店。第一家在城东,第二家在城西,顾客不必全挤到街角总店——这就是“水平扩展”的思路:不升级一台机器的配置,而是增加更多机器共同分担压力。
特征存储的水平扩展核心是分片(Sharding)。把所有特征数据按某个规则切分成多份,每一份放在一个独立节点上,就是分片。关键在于路由算法:给定一条特征(比如 user_9527 的 click_count),怎么知道它存在哪个分片?最常见的做法是对特征键做哈希取模:hash(key) % N,结果就是分片编号。这就好比老王按顾客手机尾号分配分店,尾号 0-4 去城东,尾号 5-9 去城西,公平又高效。
但水平扩展不是无限加速的,Amdahl 定律给出了天花板:
负载均衡也很关键:哈希取模虽然均匀,但热点特征(如头部用户)会造成个别分片过载,所以还需要动态均衡策略,例如一致性哈希或按负载迁移数据。老王发现城东店旁边开了个网红奶茶店,客流暴增,于是临时把部分热门商品调货到城西店——这就是负载均衡的朴素版本。最后要记住,分片数并非越多越好,元数据管理、跨分片查询、网络开销都会随 N 增长,这就是扩展上限。
- 并行占比 p可并行处理部分占全部工作的比例,比如收银、理货可以分摊到各分店。
- 节点数 N 与串行部分N 是节点数,$(1-p)$ 是不可并行的串行比例,不会随节点增加而减少。
- 加速比 S_N整体公式表达扩展后性能提升的倍数,当 p < 1 时 N 再大也有上限。
分区策略
分店开多了,老王发现每个店都把所有货品堆在一起很混乱。于是他规定:城东店以生鲜为主,城西店以日用品为主,每家店内再按“临期区、常规区”细分。顾客进门直奔对应区域,找货快,补货也高效。这个思路对应特征存储的分区策略。
分区与分片不同:分片是把数据打散到不同机器,分区则是在一个逻辑范围内进一步切分,通常有两类。时间分区按日期划分特征数据,便于按时间窗口淘汰旧数据、做增量更新;实体分区按业务实体(如用户 ID 段)划分,让同一实体的特征尽量落在同一分区,避免查询跨区拉取。分区数量不是拍脑袋定的:
分区裁剪(Partition Pruning)是分区带来的最大红利:查询时带上分区条件,系统直接跳过无关分区。比如老王查“3 月的销售”,只翻 3 月的账本,不必翻全年。最后要注意粒度权衡:分区太细,元数据膨胀、查询 fan-out 多;分区太粗,裁剪失效、扫描数据量大。找到“查询常用维度”与“数据均匀分布”的交点,就是最优分区键。
- 数据总量 V_\text{total}需要存储的全部特征数据体积,类似仓库总货物箱数。
- 单分区上限 V_\text{limit}单个分区可管理的数据量上限,由查询性能和维护成本共同决定。
- 向上取整的分区数两者相除后向上取整,保证分区数既能覆盖全部数据又不冗余。
缓存设计
老王发现,销量最高的永远是门口那几款爆品——老干妈、矿泉水、香烟。与其让顾客每次都在货架间翻找,不如把爆品摆在门口随手拿。这就是缓存的精髓:把高频访问的数据放到离用户最近、最快的地方。
特征存储的缓存设计通常分两层:本地缓存(L1)放在应用进程内,走内存访问,纳秒级返回;分布式缓存(L2)如 Redis 放在存储引擎之前,承担大规模读取。两层配合,就像门店货架加仓库前置仓:货架没货,先从前置仓调,不必每次去总仓拉货。缓存好不好,核心看命中率:
缓存还需要三个配套机制。第一,淘汰策略:缓存空间有限,常用 LRU(最近最久未使用)把长期没人碰的货下架。第二,穿透防护:若大量请求查询一个根本不存在的 key,缓存永远“漏”下去直击存储,需要用布隆过滤器先拦截“肯定不存在”的请求,或对空结果短暂缓存。第三,缓存一致性:特征更新后要尽快让缓存失效或刷新,否则模型拿到的特征可能是“昨天的旧报纸”。老王的做法是:进货单(特征写入)一到,立刻通知各分店撤掉对应旧货——主动失效。
- 命中次数 H_\text{hit}数据在缓存中直接返回的请求次数,即顾客直接从门口拿走爆品的次数。
- 未命中次数 H_\text{miss}缓存缺失、需要回源底层存储的请求次数,即去仓库翻找的次数。
- 命中率计算命中次数除以总请求数,结果越接近 1 说明缓存越有效。
一致性保障
连锁店多了,账怎么对?老王一开始每天打烊后让各分店报账,夜里总店汇总,第二天早上各店数据才一致。白天的某一刻,城东店的账本和城西店可能不一样——但大家心里有数:到明早一定对齐。这就是“最终一致性”。
特征存储天然是分布式系统,写入一个特征后,各副本之间通过异步同步达到一致,存在一个收敛时间窗口。这个窗口受传播、重试等因素影响:
特征平台里最头疼的其实不是副本同步,而是“离线在线一致性”。离线特征(用于训练)和在线特征(用于推理)如果由两套代码、两条流水线生成,值就会对不上——模型训练时看到的是“常温的昨天”,上线推理时拿到的是“刚出锅的现在”,效果必然打折。解决思路是:同一份特征定义代码同时生成离线表和在线服务,线上再打点回流到离线,确保口径一致。
最后是版本管理与冲突处理。特征会有更新,模型会引用特定版本;当两个请求并发写同一特征时,需要靠乐观锁(版本号对比)或时间戳策略决定谁生效。老王的对策也简单:每本账册都有版号,对不上号的账先不认,以版号新的为准——宁可晚一点对齐,不许错着记账。
- 传播时间 T_\text{prop}数据从写入节点同步到其他副本的时间,类似各分店把账本寄到总店。
- 重试时间 T_\text{retry}网络抖动导致同步失败、重新发送的额外开销。
- 时钟偏差与收敛公式各节点时钟不完全同步,留出 ε 余量;三者相加就是最终一致性的最大收敛窗口。
高可用架构
老王最怕什么?分店着火、水管爆了、员工集体请假。于是他定下规矩:每家店的重要货品,隔壁店都留一份备份;万一哪家店出问题,顾客直接分流到附近门店。这就是高可用架构的雏形。
特征存储的高可用,首先靠主从复制:主节点负责写,从节点同步数据并负责读。当主节点宕机,从节点中选一个提升为新的主节点,系统继续对外服务,这就是故障切换(Failover)。整个过程对外几乎无感知,就像城东店临时关门时,顾客被引导到 200 米外的城西店,生意照做。
可用性是有数学标尺的:
容灾设计则更进一步:在同一城市多机房部署,甚至跨城市异地多活。老王后来把总账本在隔壁城市也存了一份,哪怕全城停电,云仓还能照常发货。可用性指标(SLA)是团队之间签的“军令状”:承诺 99.9% 可用,意味着全年最多允许 8.76 小时故障,所有架构设计都要围着这个数字倒推。
- MTBF 平均故障间隔两次故障之间系统正常工作的平均时长,故障越少数值越大。
- MTTR 平均修复时间从故障发生到恢复服务所需的平均时长,修复越快数值越小。
- 可用性占比正常时间除以总时间,公式结果越接近 1,系统越可靠。
性能监控
老王为每家店装了客流计数器、装了摄像头,每天看报表:几点是高峰、哪个货架被翻得最乱、哪家店客单价下滑。没有这些数据,他说不清该往哪加人、往哪补货。特征存储的扩展也一样,必须“先观测,再扩容”。
延迟监控最常用的指标是 P99 分位延迟。平均延迟会被大部分正常请求“带偏”,掩盖那些极慢的“尾请求”;P99 则告诉你:99% 的请求比它快,剩下的 1% 就是需要警惕的尾巴。计算公式要在排序后的延迟样本中取位置:
吞吐监控关注 QPS 与 CPU、内存、网络使用率的关系,判断系统离饱和还有多远。容量规划则在监控基础上做趋势外推:按当前增速,3 个月后 QPS 会达到多少?要不要提前加节点?告警策略是最后一道防线:P99 超过阈值、错误率上升、节点心跳丢失,都要立即触发告警,把问题消灭在用户感知之前。老王给店员定的规矩是:冰柜温度一超 -18℃ 必须 10 分钟内上报——特征存储里的告警,同样分秒必争。
- N 个延迟样本统计窗口内收集的请求延迟数据,样本越多统计越可靠。
- 排序与百分位位置延迟从小到大排列后,用 0.99 乘以 N 并向上取整,得到目标位置索引。
- P99 取值在排序数列中取出该位置的值 x,即最慢 1% 请求的分界线。
存储分层
随着生意越做越大,老王的仓库堆满了货。他仔细盘了盘,发现有些货每天出库,有些一周动一次,有些一年都碰不到。如果把所有货都放在最贵的冷链库里,成本高得离谱。于是他把仓库分成三层:门店冷柜放热货、常温仓放温货、偏远仓库放冷货——特征存储的存储分层,就是这个道理。
特征数据的访问热度差异巨大:在线推理常用的特征毫秒级访问,属于热数据;训练集用的历史特征偶尔读取,属于温数据;一年多前的特征基本无人问津,属于冷数据。设计上让热数据存内存或 SSD,温数据存 HDD,冷数据存低成本对象存储,综合成本达到最优:
配合压缩策略,冷数据可用高压缩比算法(如 ZSTD)进一步瘦身,减少 70% 以上空间。生命周期管理则负责自动流转:新特征写入热层,30 天后降为温层,180 天后转冷层,全程无需人工干预。老王最后感慨:当初如果一口气把所有货都买冷柜存着,早就破产了。特征平台同样要把每一分存储成本花在刀刃上。
- 各层体积 V热、温、冷三层实际存储的数据量,通常逐层增大。
- 各层单价 C单位数据量的存储成本,SSD 最贵、HDD 居中、对象存储最便宜。
- 加权求和总成本三组乘积相加得到总成本,体现了分层后成本与性能的平衡。
AI 应用场景
场景一:金融风控特征平台弹性扩容
阶段:特征存储与在线推理
解决的问题:传统风控系统把特征存在单机数据库,大促期间请求量暴涨 10 倍,数据库连接打满、接口超时,风控决策形同虚设。采用水平扩展 + 缓存分层后,将特征按用户 ID 哈希分片到多个节点,热点用户特征常驻 L1 缓存,QPS 提升 15 倍,P99 延迟稳定在 50ms 以内。
具体案例:某支付平台在双 11 期间,风控特征存储节点从 20 个自动扩容到 80 个,扩容过程平滑无感知。监控系统提前一周根据 QPS 趋势预测出容量缺口,自动触发扩容流程,大促当天零故障。
场景二:推荐系统离线在线特征一致性保障
阶段:特征工程与训练推理一致性
解决的问题:推荐模型训练时用离线特征表,线上推理时从在线特征服务读取,两边数值经常对不上,导致模型上线后效果回退。采用“同一份特征定义代码生成离线表 + 在线服务”的方案,并上线特征打点回流,将离线在线差异率从 8% 降到 0.1%。
具体案例:某短视频推荐团队重构特征流水线后,模型上线不再需要“预热校准”,新模型 A/B 测试通过率提升 40%,训练与推理的 gap 大幅收窄。
场景三:物联网设备特征存储成本优化
阶段:特征存储生命周期管理
解决的问题:IoT 平台每天写入数十亿条设备特征,全部存 SSD 成本爆炸。采用热温冷分层:实时告警用热层,小时级分析用温层,月度报表用冷层,配合生命周期自动降级,存储综合成本下降 65%。
具体案例:某智能家居厂商将设备特征按“最近 7 天热存 + 90 天温存 + 之后冷存”策略落地,查询性能没有明显退化,年度存储预算节省超过 500 万元。
Python 演示
import hashlibimport timeimport randomfrom collections import defaultdict class FeatureShard: """单个特征存储分片, 延迟随负载上升而上升""" def __init__(self, shard_id): self.shard_id = shard_id self.features = {} self.pending = 0 def get(self, key): self.pending += 1 delay = 0.2 + self.pending * 0.02 time.sleep(delay / 1000.0) self.pending -= 1 return self.features.get(key) def put(self, key, value): self.features[key] = value class FeatureStore: """水平扩展的特征存储, 哈希取模路由到分片""" def __init__(self, shard_count=2): self.shards = [FeatureShard(i) for i in range(shard_count)] def _shard_index(self, key): digest = hashlib.md5(key.encode()).hexdigest() return int(digest, 16) % len(self.shards) def get_feature(self, entity_id, feature_name): key = entity_id + ":" + feature_name shard = self.shards[self._shard_index(key)] start = time.time() value = shard.get(key) latency = (time.time() - start) * 1000 return value, latency, shard.shard_id def set_feature(self, entity_id, feature_name, value): key = entity_id + ":" + feature_name shard = self.shards[self._shard_index(key)] shard.put(key, value) def add_shard(self): """水平扩展: 新增一个分片并重新分布全部数据""" old_count = len(self.shards) new_shards = [FeatureShard(i) for i in range(old_count + 1)] for shard in self.shards: for key, value in shard.features.items(): new_index = int(hashlib.md5(key.encode()).hexdigest(), 16) % (old_count + 1) new_shards[new_index].put(key, value) self.shards = new_shards def simulate_load(store, n_requests=200, entity_count=50): """模拟请求压力, 统计各分片负载与平均延迟""" load = defaultdict(int) latencies = [] for _ in range(n_requests): entity_id = "user_" + str(random.randint(0, entity_count)) value, latency, shard_id = store.get_feature(entity_id, "click_count") load[shard_id] += 1 latencies.append(latency) avg_latency = sum(latencies) / len(latencies) return load, round(avg_latency, 3) if __name__ == "__main__": store = FeatureStore(shard_count=2) for i in range(100): store.set_feature("user_" + str(i), "click_count", random.randint(0, 1000)) load_2, avg_2 = simulate_load(store) print("2-shard load:", dict(load_2), "avg latency:", avg_2, "ms") store.add_shard() load_3, avg_3 = simulate_load(store) print("3-shard load:", dict(load_3), "avg latency:", avg_3, "ms") print("Expansion improved latency:", avg_3 < avg_2)
self.pending += 1记录该分片当前处理的请求数,模拟排队效应:请求越多响应越慢,对应“瓶颈分析”中的延迟飙升。delay = 0.2 + self.pending * 0.02延迟与分片负载挂钩,是理解“扩展降低延迟”的关键模拟逻辑。store.add_shard()水平扩展的直观实现:新增一个分片,并重新计算所有已有数据的归属,模拟真实系统中的数据迁移。
常见误区
误区很多初学者认为特征存储性能不够就加节点,加一倍节点性能就翻一倍,根本不用管数据分布和应用设计。
正解Amdahl 定律告诉我们,串行部分(元数据管理、跨分片协调、数据迁移)不会随节点数减少,扩展收益会逐步递减。而且节点增多后网络开销、一致性同步成本都会上升,甚至可能因负载不均导致部分节点过载。水平扩展的正确姿势是“先优化数据分布和查询模式,再扩容”。
为何常见:云计算时代“弹性伸缩”宣传深入人心,大家都见过加机器就变快的演示,容易忽略分布式系统的各种开销。
误区既然分区能裁剪加速查询,那就把数据切成几千个小区间,每个查询只扫一个小区间,性能肯定最好。
正解分区太细会带来两个问题:一是元数据膨胀,管理上千个分区的开销本身就不小;二是查询往往需要跨多个分区聚合(fan-out),结果合并的网络和计算成本反而更高。分区粒度应结合查询模式和数据量权衡,让“常用查询最多扫描 2-3 个分区”为宜。
为何常见:把“裁剪加速”当成免费午餐,忽略了分区数量和元数据、查询 fan-out 之间的此消彼长。
误区缓存命中率是缓存设计的唯一指标,把命中率从 90% 优化到 99% 一定是好事。
正解缓存命中率提升到后期,需要投入更大的内存容量或更复杂的淘汰策略,而且过热的缓存会带来一致性风险:数据更新后旧值在新缓存中滞留更久。特征存储的缓存目标应该是“在满足延迟 SLA 的前提下控制成本”,而不是无限追求命中率。
为何常见:缓存命中率直观易懂,很多文章拿它当性能标杆,容易让人忽视背后的成本与一致性代价。
误区既然不是强一致,那读到旧数据也没关系,反正“最终”会一致,什么时候一致无所谓。
正解最终一致性有一个收敛窗口,这个窗口必须在 SLA 内(比如 10 秒),超出窗口仍然读到旧值就属于故障。特征存储中离线在线一致性差异过大会直接导致模型效果下降,所以收敛窗口要监控、要优化,不能放任不管。
为何常见:对“最终”两个字望文生义,以为数据状态不重要,忽视了收敛时间这个真实约束。
误区只要离线特征表和在线特征服务由同一份代码生成,两边数据就天然对齐,不用再做校验。
正解代码相同只能保证“计算逻辑一致”,但数据源、时间窗口、数据漂移仍可能造成差异。比如离线训练用 T-1 数据,在线推理用实时数据,两者在聚合窗口边缘就可能不一致。正规做法是定期做“特征一致性对账”,用线上真实请求与离线计算结果对比,差异率超过阈值就告警。
为何常见:把“同一份代码”理想化为“完全一致”,忽略了输入数据和时间语义的差异。
面试题
Q1. 特征存储水平扩展相较于垂直扩展的核心优势是什么?
- A.通过增加节点分摊请求压力← 正确答案
- B.单机 CPU 频率显著提升
- C.完全消除网络传输开销
- D.不再需要进行数据备份
答案:A。水平扩展通过增加节点分摊请求压力,是特征存储应对流量增长的主要手段。垂直扩展受单机硬件上限约束,网络开销和备份在任何分布式系统中都不可避免,因此 B、C、D 错误。
Q2. 特征存储分片时最常用的数据路由方法是?
- A.按写入时间顺序轮询分配
- B.将数据复制到全部节点
- C.对特征键哈希取模定位分片← 正确答案
- D.由客户端随机挑选节点
答案:C。哈希取模(hash(key) % N)能将数据均匀分布到各分片,且任一特征键都能稳定路由到同一分片。轮询和随机分配会导致查询时无法定位数据位置,全量复制则浪费存储空间。与老王按手机尾号分流顾客到分店同理。
Q3. 缓存穿透指的是以下哪种情况?
- A.缓存中数据过期需要回源刷新
- B.缓存服务器之间数据不一致
- C.大量请求查询不存在的数据击穿缓存← 正确答案
- D.缓存容量不足导致数据淘汰
答案:C。缓存穿透是查询根本不存在的 key,缓存层永远无法命中,请求直接打到存储层。布隆过滤器或空值缓存可拦截这类请求。A 是缓存过期、B 是缓存一致性、D 是容量问题,均与穿透不同。
Q4. 关于 P99 延迟指标,下列说法正确的是?
- A.P99 表示 99% 的请求比该值更快← 正确答案
- B.P99 是所有请求延迟的平均值
- C.P99 是最慢 99% 请求的均值
- D.P99 等于所有请求的最大延迟
答案:A。P99 是排序后第 99 百分位的延迟值,表示 99% 的请求体验优于该值,剩余 1% 为尾延迟。平均值会被大量正常请求掩盖痛点,最大值则受偶然抖动影响,两者都不是衡量尾延迟的稳定指标。
Q5. 在可用性公式 A = MTBF / (MTBF + MTTR) 中,降低 MTTR 的效果是?
- A.提高故障发生的频率
- B.增加正常工作时间总量
- C.缩短故障恢复的时间← 正确答案
- D.减少数据同步的网络延迟
答案:C。MTTR 是平均修复时间,降低它意味着故障恢复更快,分母变小,可用性 A 上升。MTBF 是故障间隔时间,降低 MTTR 不会改变故障发生频率,也不会延长无故障时长或影响同步延迟。
Q6. 特征存储中“热温冷分层”方案设计的核心目标是?
- A.降低存储成本并保障访问性能← 正确答案
- B.提升单机 CPU 的主频
- C.增加数据的副本数量
- D.简化特征的写入流程
答案:A。热数据放内存或 SSD 保障在线访问性能,冷数据放低成本对象存储分摊体积,加权总成本最低。这与 CPU 主频、副本数量、写入流程无关。老王把热货放门店冷柜、冷货放偏远仓库,同是一个账本。
Q7. 水平扩展后,Amdahl 定律揭示的性能天花板来自?
- A.系统中不可并行的串行部分← 正确答案
- B.网络带宽不足限制了扩展
- C.节点磁盘容量过小限制性能
- D.客户端并发数过高导致阻塞
答案:A。Amdahl 定律指出,加速比上限由串行占比 (1-p) 决定,无论节点 N 多大,串行部分都无法被分摊。用老王的分店打比方:统一进货、统一账务永远需要人手,这部分成了效率天花板。
Q8. 以下哪些设计可以有效缓解特征存储的缓存穿透问题?
- A.对不存在 key 做短期空值缓存← 正确答案
- B.使用布隆过滤器预判 key 是否存在← 正确答案
- C.在存储层前置限流与熔断保护← 正确答案
- D.直接扩大缓存层内存总容量
答案:ABC。空值缓存让“查不到的 key”也短暂缓存,布隆过滤器把“肯定不存在”的请求挡在缓存外,限流熔断保护存储层——三管齐下应对穿透。而加内存只是提高缓存容量,不能解决“无效 key 永远击穿”的问题。
Q9. 保障离线特征与在线特征一致性的常见工程手段有哪些?
- A.同一份特征代码生成离线在线特征← 正确答案
- B.线上特征打点回流到离线训练数据← 正确答案
- C.定期对账并监控离线在线差异率← 正确答案
- D.离线表和在线服务各自独立优化
答案:ABC。同一份代码保证计算逻辑一致,打点回流让离线数据覆盖真实线上分布,对账监控兜底发现漂移。D 独立优化正是“两套代码两套口径”的坏味道,会放大训练推理 gap。
Q10. 关于特征存储高可用设计,以下说法正确的有?
- A.主从复制可以把读流量分摊到从节点← 正确答案
- B.故障切换需要心跳检测与自动选主机制← 正确答案
- C.跨机房容灾可抵御单机房级故障← 正确答案
- D.高可用设计可以完全容忍网络分区
答案:ABC。主从复制中从节点承担读请求、主节点负责写,心跳检测触发选主实现自动故障切换,异地多活应对机房级灾难。但网络分区下必然面临一致性与可用性权衡(CAP 理论),没有任何设计能“完全容忍”网络分区,D 错误。