想象一座城市把所有公共图书馆联合成一个联盟:市民在任意分馆都能查到全城每一本书的位置。这需要一套聪明的协调系统——总调度室记录各分馆状态,把藏书按规则分散到不同分馆,某个分馆出事时迅速让备份顶上。Solr Cloud就是搜索引擎世界的“图书馆联盟”,它用ZooKeeper做总调度室,把一份庞大索引切成多个分片存放在不同节点,每个分片有“馆长”负责写入、“副馆长”负责备份。而Elasticsearch是另一套采用不同管理方式的联盟。这篇文章用“图书馆联盟”的故事,从七个维度带你拆解分布式搜索集群的运作原理。

岗位关联

对AI从业者而言,理解Solr Cloud的协调、分片、复制与故障转移机制,是设计高可用搜索架构的底层能力,也是搜索平台选型时必备的判断力。

目录
  1. 可视化演示
  2. ZooKeeper集群协调:联盟的总调度室
  3. Collection与Shard:藏书体系和分馆分区
  4. Leader选举机制:分馆馆长的交接仪式
  5. 索引复制机制:新书上架的编目同步
  6. 架构差异对比:传统联盟 vs 数字原生
  7. 运维复杂度对比:养一个调度室要多少人力
  8. 功能特性选型:图书馆该选哪种模式
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

展示Solr Cloud集群架构:ZooKeeper协调、Collection分片管理、Leader选举与索引复制机制,以及Hash分片路由策略的文档分布过程。

本节配有交互动效(进入视口后自动加载,约 3KB)。

Solr Cloud集群写入流程 ZooKeeper协调配置中心和Leader选举 Leader分发到所有Follower副本确认 write -> leader -> replicas -> ack 分布式事务保证一致性

ZooKeeper集群协调:联盟的总调度室

图书馆联盟开张第一天,最要紧的是建一个总调度室。联盟里每个分馆开馆前都要向调度室报到,告诉调度室自己的地址、藏书范围、营业状态。调度室用一个大本子记录三样东西:哪些分馆正在营业、全联盟统一的规章制度、哪批书放在哪个分馆。分馆之间不直接联系,所有信息都通过调度室中转——这就是ZooKeeper在Solr Cloud中扮演的角色。

ZooKeeper是一个高可用的分布式协调服务,它维护着Solr Cloud集群的全局状态。当一个新的Solr节点启动时,会向ZooKeeper注册并建立会话,之后通过心跳保持连接。ZooKeeper利用临时节点(Ephemeral Node)的自动过期特性来感知节点故障——一旦节点心跳超时,临时节点自动消失,集群中的其他节点立刻收到通知。除了节点状态,ZooKeeper还集中存储集群的配置文件(如solr.xml、schema.xml)以及Collection与Shard的映射关系,任何节点都能随时读取最新配置。

回到图书馆的比喻:总调度室的大本子上记着“营业分馆清单”“联盟规章制度”“图书分布地图”三份档案,任何分馆需要信息,问调度室即可。正因如此,Solr Cloud节点之间无需互相知晓对方地址,通信复杂度被ZooKeeper集中收拢,这正是集群协调的精髓。

Zstate=(Nlive,  Cconfig,  Smapping)\displaystyle Z_{\text{state}} = \left( N_{\text{live}},\; C_{\text{config}},\; S_{\text{mapping}} \right)
这个公式表示ZooKeeper协调器维护的三元组:存活节点集合、全局配置、分片映射关系。
  1. 存活节点集合N_live是当前存活的节点集合,由ZooKeeper的心跳检测和临时节点机制动态维护
    Nlive={n1,n2,…,nk}N_{\text{live}} = \{ n_1, n_2, \dots, n_k \}
  2. 全局配置集合C_config是集中管理的配置信息,节点启动或配置变更时从ZooKeeper拉取
    Cconfig={solr.xml,  schema.xml,  core.properties}C_{\text{config}} = \{ \text{solr.xml},\; \text{schema.xml},\; \text{core.properties} \}
  3. 分片映射关系S_mapping记录哪个Shard属于哪个Collection、分布在哪个节点上
    Smapping:Shard→NodeS_{\text{mapping}} : \text{Shard} \rightarrow \text{Node}

Collection与Shard:藏书体系和分馆分区

联盟决定把“文学类藏书”当作一套完整的藏书体系,但它不会把整套书堆在一个分馆——那样既装不下,读者集中在一处也拥挤。于是联盟把藏书包按字母分成A-M、N-Z两区(分片),A-M放1号馆,N-Z放2号馆。读者查书时,前台根据书名的首字母快速判断该去哪个馆。

Solr Cloud中的Collection就是逻辑上的索引集合(类似Elasticsearch的Index),创建Collection时指定numShards(分片数)和replicationFactor(副本因子)。每个Shard是一个独立的Lucene索引,分布在不同的物理节点上。写入文档时,Solr使用哈希路由将文档映射到具体分片——同一文档永远只会路由到同一个分片,保证查询时只需访问一个分片。

哈希取模的妙处在于“均匀且可重复”。均匀性让文档近似平均地分散到各分片,避免某个分片成为热点;可重复性让查询时能精确找到文档所在分片。这就像按首字母分流既均衡了各馆压力,又能让读者秒级定位藏书位置。

shard=hash(docId) mod Nshards\displaystyle \text{shard} = \mathrm{hash}(\text{docId}) \bmod N_{\text{shards}}
文档ID经过哈希运算后对分片数取模,结果就是文档归属的分片编号,类似按书名首字母分流。
  1. 哈希运算对文档ID做一次确定性哈希,得到一个大整数
    hash(docId)\mathrm{hash}(\text{docId})
  2. 取模运算对总分数取模,把哈希值映射到0到N-1的分片编号区间
     mod   Nshards\bmod \; N_{\text{shards}}
  3. 路由结果取模结果即文档所在分片,同一文档永远落在同一分片
    shard∈{0,1,…,Nshards−1}\text{shard} \in \{ 0, 1, \dots, N_{\text{shards}} - 1 \}

Leader选举机制:分馆馆长的交接仪式

每个分馆设置一名馆长和若干名副馆长。馆长负责接收新书入库(写入请求),副馆长负责对外借阅(查询请求)。某天馆长突发疾病离职,总调度室必须立即从副馆长中指定新馆长,否则新书无法进库。整个过程分三步:察觉馆长失联、召集副馆长投票、新馆长接管账目。

Solr Cloud的Leader选举正遵循这一流程。每个Shard的多个副本中有一个是Leader,所有写入请求必须先到达Leader(保证写入顺序),Replica负责处理查询。ZooKeeper通过创建临时顺序节点完成选举:每个候选节点在ZooKeeper的选举目录下创建带序号的临时节点,序号最小者成为Leader;其他候选节点监听前一个节点的状态,一旦Leader消失便重新竞争。

选举机制的巧妙之处在于“你永远不知道哪天需要它”。只要Leader存活,这套机制静默潜伏;一旦Leader故障,ZooKeeper在秒级完成交接,让集群写入能力快速恢复。这正是分布式系统“无单点故障”承诺的基础,就像联盟永远不会因为一位馆长离职而停止进新书。

Telection=Tdetect+Tvote+Tsync\displaystyle T_{\text{election}} = T_{\text{detect}} + T_{\text{vote}} + T_{\text{sync}}
Leader交接的耗时由故障发现时间、选举投票时间和数据同步时间三部分构成。
  1. 故障检测时间ZooKeeper会话超时后确认Leader失联所需时间
    Tdetect=SessionTimeout+δT_{\text{detect}} = \text{SessionTimeout} + \delta
  2. 选举投票时间候选节点创建顺序节点、比较序号、选出最小者的时间开销
    Tvote=O(n)T_{\text{vote}} = O(n)
  3. 数据同步时间新Leader从旧Replica节点拉取最新索引数据追平进度的耗时
    Tsync=SindexBnetT_{\text{sync}} = \frac{S_{\text{index}}}{B_{\text{net}}}

索引复制机制:新书上架的编目同步

图书馆采购了一本新书,馆长在馆内系统登记完毕后,必须立刻把编目卡片同步给所有副馆长。这样读者无论走进哪家分馆,都能查到这本书。如果只有馆长手上有编目而馆长突然辞职,这本新书就从联盟“凭空消失”了——这就是复制机制的初衷。

Solr Cloud通过replicationFactor参数控制每个Shard的副本数量。replicationFactor=3表示每个Shard有3份数据(1个Leader+2个Replica)。写入流程是:客户端向Leader提交文档→Leader更新本地索引并记录UpdateLog→Leader将更新推送给所有Replica→Replica确认完成后返回成功。查询请求则可以分发到任意副本,实现读写分离,提升吞吐量。

举个例子:若单节点年故障率是5%(p=0.05),3副本的数据可用性约为99.875%,5副本则高达99.999%。重要文件抄了多份放在不同房间,全部被销毁的概率自然极低。副本数量每增加一个,可用性就向上抬升一个台阶,但存储成本和写入延迟也随之上升——这是高可用与成本之间的经典权衡。

A=1−(1−p)r\displaystyle A = 1 - (1 - p)^{r}
当每个节点的故障概率为p、副本数为r时,数据可用性等于至少一个副本存活存活的概率。
  1. 单节点故障概率p表示单个节点在单位时间内发生故障的概率(0到1之间)
    p∈[0,1]p \in [0, 1]
  2. 全部副本故障概率r个副本同时故障的概率是单节点故障概率的连乘
    (1−p)r(1 - p)^{r}
  3. 可用性公式用整体1减去“全部失效”的情形,得到至少一个副本存活的概率
    A=1−(1−p)rA = 1 - (1 - p)^{r}

架构差异对比:传统联盟 vs 数字原生

传统图书馆联盟需要额外聘请一个调度室团队,所有分馆的入网登记、状态上报都要人工处理。而另一座城市的“数字原生”图书馆联盟把调度逻辑内置在每台自助借阅机里,馆员之间通过广播自动发现彼此,不需要专门的总调度室。Solr和Elasticsearch正是这两种思路的代表。

Solr Cloud强依赖ZooKeeper作为外部协调组件,用户需要额外部署3或5节点的ZooKeeper集群;而Elasticsearch从1.x到7.x的演进中,逐步用内置的ZenDiscovery和后来的集群协调协议替代了外部ZK依赖。节点角色上,ES明确定义了Master、Data、Ingest等角色,Solr节点则职责统一、由ZooKeeper动态分配任务。数据模型方面,Solr用schema.xml严格定义字段类型,写入前必须匹配模式;ES采用JSON动态映射,字段可以自动推断类型。

ES把这份“3节点起步、过半才能活”的复杂度内置到了自家节点中,对用户更友好。而Solr的ZK集群虽然增加了一层运维负担,但这也意味着协调逻辑可以独立于搜索节点运行,两者互不干扰,让追求极致掌控力的团队拥有更多调优空间。

Nzk≥3,Nquorum=⌊Nzk2⌋+1\displaystyle N_{\text{zk}} \geq 3, \quad N_{\text{quorum}} = \left\lfloor \frac{N_{\text{zk}}}{2} \right\rfloor + 1
ZooKeeper集群需至少3个节点,且过半节点存活(多数派)才能对外提供服务。
  1. 最小节点数ZooKeeper集群至少3个节点,因为少于3无法形成多数派
    Nzk≥3N_{\text{zk}} \geq 3
  2. 多数派计算quorum是过半存活数,3节点容错1个、5节点容错2个
    Nquorum=⌊Nzk2⌋+1N_{\text{quorum}} = \left\lfloor \frac{N_{\text{zk}}}{2} \right\rfloor + 1
  3. 奇数原则ZooKeeper集群推荐奇数节点(3/5/7),偶数节点数会造成容错能力浪费
    Nzk∈{3,5,7}N_{\text{zk}} \in \{ 3, 5, 7 \}

运维复杂度对比:养一个调度室要多少人力

传统联盟要额外养一支调度室团队:培训调度员、维护调度系统、定期演练应急流程。现代联盟把这些工作写进了软件代码里,省掉了一个团队的开支。但传统联盟的调度室并非毫无价值——它让分馆之间的协作规则更清晰、边界更明确。

Solr Cloud运维的“额外账单”包含:部署和维护ZooKeeper集群(监控会话数、JVM堆、磁盘介质)、管理多个配置文件(solr.xml、schema.xml、core.properties),以及通过Collections API手动管理分片的创建与迁移。ES则把这些操作收拢到REST API和YAML配置中,节点自动发现、自动分片分配大幅降低了上手门槛。但ES并非全无成本——它的YAGNI式封装也让深度调优时的排查难度上升。

从学习曲线上看,Solr需要同时理解Lucene、Solr和ZooKeeper三层知识,ES则把协调层封装后只需关注集群和索引两层。对于小团队和快速迭代的业务,ES的“省心”优势明显;对于已具备ZK运维经验的大团队,Solr的精细化控制可能是加分项。

Cops=Cnode×N+Czk+Ccfg\displaystyle C_{\text{ops}} = C_{\text{node}} \times N + C_{\text{zk}} + C_{\text{cfg}}
Solr Cloud的总运维成本等于节点运维成本加上ZooKeeper集群成本再加配置文件管理成本。
  1. 节点运维成本C_node是单个Solr节点的日志、磁盘、JVM监控成本,乘以节点数N
    Cnode×NC_{\text{node}} \times N
  2. ZK集群成本C_zk是Solr独有的ZooKeeper集群运维开销(部署、监控、容灾)
    CzkC_{\text{zk}}
  3. 配置管理成本C_cfg是管理多份XML配置文件的成本,Solr的配置项比ES更多更细
    CcfgC_{\text{cfg}}

功能特性选型:图书馆该选哪种模式

读者偏好五花八门:老学究喜欢传统图书馆的精美检索卡片和编目体系,年轻人则更习惯手机App下单、自助取书。选哪种图书馆模式,取决于你的主流读者是谁。Solr和ES在功能特性上的分野,恰好对应了“专业检索”与“实时平台”两种价值取向。

Solr在复杂布尔查询、facet聚合统计、相关性排序等传统检索领域沉淀深厚,配合IK分词器在中文场景表现优异;ES则在近实时搜索(写入秒级可见)、日志分析(ELK全家桶)和云原生部署上占尽先机,社区活跃度和生态工具数量遥遥领先。选型时建议列出业务的核心维度(检索精度、实时性、运维成本、生态支持),为每个维度打分再加权求和。

把“检索精度5分、实时性8分、运维成本6分、生态支持9分”的评分表分别填给两个系统,加权算出的总分就是你的选型答案。没有绝对的好坏,只有“在当下的业务约束下,谁更合适”——这正是架构师的核心判断力。

---

Score=∑i=1nwi×si\displaystyle \text{Score} = \sum_{i=1}^{n} w_i \times s_i
选型评分等于每个需求维度的权重乘以系统在该维度的能力评分,加权求和得出总分。
  1. 权重向量w_i代表第i个维度的业务重要性,权重和为1
    ∑i=1nwi=1\sum_{i=1}^{n} w_i = 1
  2. 能力评分s_i是搜索平台在第i个维度的能力评分(1到10分制)
    si∈[1,10]s_i \in [1, 10]
  3. 加权求和每个维度的权重与评分相乘后累加,总分高者胜出
    Score=w1s1+w2s2+⋯+wnsn\text{Score} = w_1 s_1 + w_2 s_2 + \cdots + w_n s_n

AI 应用场景

企业搜索引擎架构选型

阶段:技术调研与选型

解决的问题:业务需要全文检索能力,但团队在Solr与Elasticsearch之间犹豫不决。传统方式是凭直觉选型,结果上线后才发现实时性、运维能力与团队技能栈不匹配。用本文的加权评分模型,把检索精度、实时性、运维成本、生态支持四个维度量化打分,选型从“拍脑袋”变成“算总分”。

具体案例:某电商平台重建商品搜索,团队深耕Java生态且已有ZooKeeper运维经验,最终选定Solr Cloud。通过ZooKeeper调度6节点集群,使用IK分词处理中文商品名,配合facet聚合实现品牌、价格区间筛选,稳定支撑日均2000万次查询。

集群扩容与故障自愈保障

阶段:基础设施运维

解决的问题:大促前夕集群容量不够,按传统方式需要停机扩节点(影响线上服务),且突发宕机时手动切换耗时长达小时级。Solr Cloud的ZooKeeper协调机制让扩容变为在线操作,故障转移缩至秒级。

具体案例:618大促前,运维团队通过Solr Cloud的Collections API动态增加Shard数量,ZooKeeper自动完成数据迁移与重均衡;大促期间一台节点宕机,ZooKeeper在秒级检测会话超时并触发Leader重新选举,查询请求由其他Replica无缝承接,用户完全无感知。

Python 演示

python79 行
import hashlib  class SolrCloudNode:    """模拟一个Solr Cloud节点"""    def __init__(self, node_id):        self.node_id = node_id        self.is_leader = False        self.alive = True        self.shards = {}     def __repr__(self):        return f"Node({self.node_id}, leader={self.is_leader}, alive={self.alive})"  class SimSolrCloud:    """模拟Solr Cloud分布式集群"""     def __init__(self, num_shards, replication_factor):        self.num_shards = num_shards        self.replication_factor = replication_factor        self.nodes = []        self.zk = {"leader_nodes": {}, "live_nodes": set(), "config": {}}        self._build_cluster()     def _build_cluster(self):        """创建节点:num_shards * rf 个节点"""        total = self.num_shards * self.replication_factor        self.nodes = [SolrCloudNode(i) for i in range(total)]        for i in range(total):            self.zk["live_nodes"].add(i)        # 每个shard的leader初始化为第一个副本        for shard in range(self.num_shards):            leader_id = shard * self.replication_factor            self.nodes[leader_id].is_leader = True            self.zk["leader_nodes"][shard] = leader_id     def route(self, doc_id):        """文档路由:hash(doc_id) % num_shards"""        digest = hashlib.md5(str(doc_id).encode()).hexdigest()        shard = int(digest, 16) % self.num_shards        return shard     def leader_failover(self, shard_id):        """Leader故障时从同分片的replica中选举新leader"""        leader = self.zk["leader_nodes"][shard_id]        self.nodes[leader].is_leader = False        self.nodes[leader].alive = False        self.zk["live_nodes"].discard(leader)        for i in range(shard_id * self.replication_factor,                       (shard_id + 1) * self.replication_factor):            if self.nodes[i].alive:                self.nodes[i].is_leader = True                self.zk["leader_nodes"][shard_id] = i                return i        return None     def index_doc(self, doc_id):        """写入文档:由Leader执行并返回路由信息"""        shard = self.route(doc_id)        leader = self.zk["leader_nodes"][shard]        print(f"文档 {doc_id} -> shard {shard},由 Leader Node{leader} 写入")        return shard, leader  if __name__ == "__main__":    cluster = SimSolrCloud(num_shards=3, replication_factor=2)    print("=== 集群初始化 ===")    print("存活的节点:", sorted(cluster.zk["live_nodes"]))    print("各分片Leader:", cluster.zk["leader_nodes"])     print("\n=== 文档写入 ===")    for doc in ["A001", "B002", "C003", "D004"]:        cluster.index_doc(doc)     print("\n=== Leader故障转移 ===")    cluster.leader_failover(shard_id=1)    print("新的Leader映射:", cluster.zk["leader_nodes"])    cluster.index_doc("E005")
目的:用不到60行代码模拟Solr Cloud的文档哈希路由、Leader写入和Leader故障转移三大核心机制,帮助你直观理解分布式搜索引擎的内部工作流程。
  1. digest = hashlib.md5(str(doc_id).encode()).hexdigest()对文档ID做MD5哈希,得到固定长度的十六进制字符串
  2. shard = int(digest, 16) % self.num_shards将哈希值转为整数并取模,计算出文档所属分片编号
  3. self.zk["leader_nodes"][shard] = i在模拟的ZooKeeper状态字典中记录该分片的新Leader
  4. if self.nodes[i].alive:从同分片的Replica中依次检查存活状态,选择第一个存活的节点接管
  5. print(f"文档 {doc_id} -> shard {shard},由 Leader Node{leader} 写入")输出文档的路由路径与写入Leader

常见误区

误区我以为搭建Solr Cloud时,每个节点都要在配置里写明其他所有节点的IP地址,否则节点之间互相找不到。六台机器就意味着六份长名单配置,加节点时要挨个改。

正解Solr Cloud的根本设计就是“节点无感知”——每个节点只需要配置ZooKeeper的地址列表,启动后向ZooKeeper注册即可。新节点加入时只需告诉它ZooKeeper在哪,其余节点自动发现它。这就像新分馆开张只需向总调度室报到,不需要亲自拜访全城所有分馆。

为何常见:从单机版Solr迁移过来的开发者习惯了“节点间两两配置”的模式,容易把单体思维带入分布式架构。

误区我以为Collection就是Shard,一个Collection存放在一个节点上,多个Collection就分布在多个节点上。

正解Collection是逻辑上的索引集合,一个Collection会被切成多个Shard分布在多个节点上,每个Shard还可能有多个Replica副本。比如一个“商品Collection”可能被切成3个Shard并存放在6个节点上(replicationFactor=2)。就像“整套文学书”是逻辑概念,实际存放时被拆到好几个分馆,每处还留了备份。

为何常见:单机Solr时代的Core概念没有分片,用户容易把逻辑集合与物理存储混为一谈。

误区我以为ZooKeeper不过是个存节点地址的小数据库,相当于服务注册中心,读写压力小、宕机影响不大。

正解ZooKeeper的职责远不止注册中心:它通过临时顺序节点实现Leader选举,通过Watch机制实时推送配置变更,通过ZAB协议保证元数据强一致。如果ZooKeeper集群不可用,Solr Cloud的整个集群将失去协调能力,新分片创建、Leader切换、配置更新全部瘫痪——调度室关门,整个联盟停摆。

为何常见:注册中心只是ZooKeeper最直观的功能,而选举、锁、配置中心等深层次机制往往被忽略。

误区既然查询可以打到任意副本上,那副本越多查询越快,给每个Shard配上10个Replica就高枕无忧了。

正解每增加一个Replica,Leader就要多推送一份同步数据,写延迟和网络带宽开销随之上升。当副本数量过大时,同步成本会拖累整体写入性能,甚至影响跨副本的一致性时间窗口。副本数需要根据“查询吞吐需求 vs 写入压力”之间的平衡来定,通常2-3个副本已能兼顾可用性与性能。

为何常见:直觉认为“读通道多了就一定快”,忽略了分布式系统中的同步放大效应。

误区我以为都是搜索引擎,把索引数据导出再导入,改改接口就能从Solr切到ES。

正解Solr的schema.xml强类型定义与ES的JSON动态映射完全不同,查询语法(Solr的q参数 vs ES的Query DSL)、分页机制、分词器插件接口都各有体系,迁移往往需要重写整套业务查询层和索引构建管道。架构选型时就要考虑“切换成本”这一项,事后再迁移代价极高。

为何常见:两者都叫“搜索引擎”,都支持REST API,容易让人低估底层实现的差异。

面试题

Q1. Solr Cloud中负责集群协调、Leader选举和元数据管理的组件是?

单选题 · easy

  • A.Redis缓存集群
  • B.Kafka消息服务
  • C.ZooKeeper集群← 正确答案
  • D.Nginx反向代理

答案:C。ZooKeeper是Solr Cloud的“总调度室”,负责维护节点状态、选举Leader、分发配置。Redis、Kafka、Nginx都承担不同的职责,但都不是Solr Cloud的协调组件。

Q2. 每个Shard的多个副本中,负责接收写入请求的节点是?

单选题 · easy

  • A.Replica副本
  • B.Leader节点← 正确答案
  • C.ZooKeeper节点
  • D.Coordinator节点

答案:B。所有写入请求必须先到Leader以保证顺序一致,Replica负责查询读取。ZooKeeper负责协调选举,Coordinator在Solr Cloud中不是标准角色。

Q3. Solr Cloud中文档路由到具体分片的方式是?

单选题 · mid

  • A.按写入顺序轮询
  • B.对文档ID哈希取模← 正确答案
  • C.随机分配算法
  • D.按时间戳均匀分布

答案:B。hash(docId) % numShards是Solr Cloud的标准路由方式,保证同一文档永远路由到相同分片且文档均匀分布。轮询和随机都无法保证“同一文档固定落点”。

Q4. 关于ZooKeeper在Solr Cloud中发挥的作用,正确的选项有哪些?

多选题 · mid

  • A.管理集群的元数据← 正确答案
  • B.协调Leader选举← 正确答案
  • C.存储业务数据文档
  • D.监控节点存活状态← 正确答案

答案:ABD。ZooKeeper管理元数据、协调选举、通过临时节点监控存活状态,但它不存业务数据——文档数据存在Solr节点的Lucene索引中。将ZooKeeper当作业务数据库是常见误解。

Q5. 某分片的Leader节点意外宕机后,集群会发生什么?

单选题 · mid

  • A.整个集群停止服务
  • B.副本接管成为新Leader← 正确答案
  • C.该分片数据永久丢失
  • D.故障节点自动重启

答案:B。ZooKeeper检测到Leader会话超时后,从该Shard的存活的Replica中选举出新的Leader,写入服务快速恢复。集群其他分片不受影响,数据有其他副本保障不丢失。

Q6. Solr Cloud与Elasticsearch在协调机制上的关键差异是?

单选题 · mid

  • A.Solr内置协调组件依赖ZK
  • B.ES内置协调Solr依赖ZK← 正确答案
  • C.两者都依赖ZooKeeper集群
  • D.两者都不需要协调组件

答案:B。Solr Cloud强依赖外部ZooKeeper,ES从早期版本开始逐步用内置的ZenDiscovery机制替代了外部ZK,到7.x已完全自管协调。这道题常考,注意方向别搞反。

Q7. 在Solr Cloud中增加Replica副本带来的收益有?

多选题 · mid

  • A.提高查询吞吐量← 正确答案
  • B.提高数据可用性← 正确答案
  • C.降低写入延迟
  • D.不增加存储成本

答案:AB。副本让查询分流到多个节点,天然提高查询吞吐;A=1-(1-p)^r公式说明副本数越多可用性越高。但副本增加会抬高存储成本、增大写同步开销,写入延迟反而上升。

Q8. 创建Collection时设置replicationFactor=3,表示?

单选题 · mid

  • A.每个分片3份副本且共3个分片
  • B.每个分片的数据复制到3个节点← 正确答案
  • C.集群总共有3个节点
  • D.每个节点存储3份数据

答案:B。replicationFactor只控制副本数量,与分片数无关。它表示每个分片有1个Leader+2个Replica共3份数据。分片数由numShards参数独立决定,3个副本不等于3个节点。

Q9. 关于Solr Cloud与ES的运维复杂度,以下说法正确的是?

单选题 · hard

  • A.Solr无需额外组件部署简单
  • B.ES需要额外部署ZK集群
  • C.Solr需额外部署ZK运维更重← 正确答案
  • D.两者运维复杂度完全相同

答案:C。Solr Cloud的运维成本包含ZooKeeper集群的部署、监控和调优,以及多份XML配置文件的管理,明显比ES更重。ES的Master选举、分片分配等协调功能内置在节点中,开箱即用。

Q10. 某团队需要构建实时日志分析平台且重视社区生态,更适合选Elasticsearch的原因是?

多选题 · hard

  • A.ES的REST API集成更便捷← 正确答案
  • B.ES内置协调部署更简单← 正确答案
  • C.ES日志分析生态更丰富← 正确答案
  • D.ES中文分词能力天然更强

答案:ABC。ES凭借REST API、内置协调机制和ELK全家桶在日志分析场景占据绝对优势。但中文分词能力并非天然优势,Solr配合IK分词在中文检索同样强大,选项D错误。