tao-8k Embedding服务灾备方案主备Xinference集群向量数据双写同步在构建基于大模型的应用时Embedding服务的稳定性和数据可靠性是核心命脉。想象一下你的智能问答系统、推荐引擎或文档检索功能因为一个Embedding服务节点宕机导致所有向量化能力瞬间瘫痪或者因为数据丢失让辛苦积累的语义知识库毁于一旦。这种风险是任何严肃的生产系统都无法承受的。今天我们就来深入探讨一个为tao-8kEmbedding模型量身打造的高可用灾备方案。这个方案的核心思想很简单不把鸡蛋放在一个篮子里。我们将通过部署主备两套Xinference集群并实现向量数据的双写同步来确保服务永不中断、数据永不丢失。无论你是正在规划生产环境的架构师还是希望提升现有服务健壮性的开发者这套清晰、可落地的方案都能为你提供直接的参考。1. 方案全景与核心价值在深入技术细节之前让我们先俯瞰整个方案的架构理解它究竟解决了什么问题。1.1 我们要解决什么痛点单一节点的Embedding服务主要面临两大风险服务中断风险硬件故障、软件崩溃、网络问题或日常维护都可能导致服务不可用进而使所有依赖向量化的上游应用功能失效。数据丢失风险生成的向量数据如果仅存储在内存或单个节点上一旦服务重启或节点失效历史向量数据将荡然无存需要重新生成耗时耗力。1.2 方案核心主备集群与双写同步我们的灾备方案通过两个关键设计来应对上述风险主备Xinference集群部署两套独立的Xinference服务一主一备。平时由主集群提供服务备集群处于热备状态。当主集群发生故障时流量可以快速、自动或手动切换到备集群实现服务的高可用。向量数据双写同步任何文本生成向量的请求都会同时发送给主备两套集群或先写主再异步同步至备。生成的向量数据会持久化到共享的外部存储如Redis、数据库、对象存储中。这样即使某个集群完全宕机另一个集群也能从共享存储中获取历史向量数据保证数据的连续性和一致性。这个方案带来的核心价值是服务高可用具备故障自动/手动切换能力极大提升SLA服务等级协议。数据可靠性向量数据持久化且多副本避免丢失。可扩展性架构为未来水平扩展多个推理节点奠定了基础。维护友好可以在不影响业务的情况下对任一集群进行升级或维护。2. 基础环境搭建部署主备tao-8k服务灾备方案建立在稳定运行的服务之上。我们首先需要在两台独立的服务器上部署主、备两个Xinference集群并加载tao-8kEmbedding模型。2.1 准备工作假设我们有两台服务器主机A主集群IP192.168.1.100主机B备集群IP192.168.1.101确保两台服务器均满足Python 3.8 环境足够的磁盘空间用于存放模型tao-8k模型约几个GB网络互通后续需要同步数据2.2 在两台主机上部署Xinference并启动tao-8k在主备两台机器上执行相同的部署操作。步骤1安装Xinferencepip install xinference[all]步骤2启动Xinference服务默认会在localhost:9997启动。为了能从其他机器访问我们指定绑定IP。# 在主机A上执行 xinference-local --host 0.0.0.0 --port 9997 # 在主机B上执行 xinference-local --host 0.0.0.0 --port 9997--host 0.0.0.0表示监听所有网络接口。步骤3通过命令行注册并启动tao-8k模型我们需要使用Xinference的客户端来注册模型。模型文件已预置在/usr/local/bin/AI-ModelScope/tao-8k。# 首先获取Xinference的客户端 xinference-client # 注册并启动tao-8k embedding模型 # 这里假设模型类型为 embedding模型格式为 ggufv2请根据实际模型格式调整。 # 我们为模型起一个唯一标识例如 tao-8k-embedding xinference launch --model-name tao-8k --model-type embedding --model-format ggufv2 --model-path /usr/local/bin/AI-ModelScope/tao-8k --replica 1关键参数解释--model-name: 自定义的模型名称用于后续调用。--model-type: 模型类型tao-8k是嵌入模型所以是embedding。--model-format: 模型文件格式需根据实际情况指定如ggufv2,pytorch等。--model-path:模型在本地的绝对路径即/usr/local/bin/AI-ModelScope/tao-8k。--replica: 副本数设置为1。步骤4验证服务启动成功部署完成后可以通过查看日志或Web UI验证。# 查看Xinference日志日志路径可能因启动方式而异 tail -f /root/workspace/xinference.log在日志中寻找模型加载成功的提示。同时你可以通过浏览器分别访问主集群Web UI:http://192.168.1.100:9997备集群Web UI:http://192.168.1.101:9997在Web UI的“已启动模型”列表中应该能看到tao-8k-embedding模型处于运行状态。至此主备两套独立的tao-8kEmbedding服务已经准备就绪。3. 灾备架构设计与数据流有了两个服务节点下一步是设计如何让它们协同工作并确保数据安全。下面是整个灾备方案的核心架构图与数据流说明。[上游应用] (如RAG系统、推荐系统) | | HTTP请求 (文本) v [负载均衡/网关] (如Nginx, API Gateway) | |-------------------[故障检测]------------------- | | v (正常流量) v (主库故障时) [主 Xinference 集群] [备 Xinference 集群] (192.168.1.100:9997) (192.168.1.101:9997) | | |--(1. 生成向量 双写)--------------------------| | | v v [外部共享存储] -----------------------------(2. 数据同步)---| (Redis / PostgreSQL / 对象存储) | | | |------------------[3. 数据读取]--------------------| | v [向量数据库] (如Milvus, Qdrant, Weaviate)数据流详解双写请求上游应用通过负载均衡器将生成嵌入向量的请求发送到当前主集群。应用端SDK或一个中间件组件在收到主集群成功响应后异步地将同一请求发送给备集群或者采用更可靠的方式将主集群返回的向量结果直接写入外部共享存储。数据同步我们不直接依赖两个Xinference集群之间的点对点同步。而是通过“双写”或“先写主存储再同步至备存储”的模式将生成的(文本, 向量)对持久化到如Redis、关系型数据库或对象存储中。备集群在启动或需要时可以从这个共享存储中读取数据。故障切换负载均衡器或网关集成健康检查定期探测主集群的/v1/embeddings端点。当主集群连续失败多次则自动将流量路由到备集群。切换后备集群承担所有新的向量生成请求并从共享存储中读取历史向量数据保证业务连续性。向量存储生成的向量最终会被索引到专业的向量数据库如Milvus中用于后续的相似性检索。向量数据库的数据源来自共享存储确保了数据源的唯一性和一致性。关键点这个设计的精髓在于解耦。服务高可用主备切换和数据可靠性外部存储由不同的组件负责架构更清晰容错能力更强。4. 核心实现客户端双写与数据持久化现在我们来编写最关键的部分一个智能的客户端它负责与主备集群通信并实现向量数据的双写与持久化。我们将创建一个Python类Tao8kEmbeddingClient它具备以下能力维护主备集群的终端地址。优先调用主集群失败时自动重试并切换至备集群。将成功生成的向量数据写入外部存储这里以Redis为例。4.1 客户端实现代码import requests import json import time import logging from typing import List, Optional, Dict, Any import redis # 需要 pip install redis logging.basicConfig(levellogging.INFO) logger logging.getLogger(__name__) class Tao8kEmbeddingClient: tao-8k Embedding高可用客户端支持主备切换与数据双写。 def __init__(self, primary_endpoint: str http://192.168.1.100:9997, secondary_endpoint: str http://192.168.1.101:9997, model_uid: str tao-8k-embedding, # 与启动模型时指定的名称一致 redis_host: str localhost, redis_port: int 6379, redis_db: int 0): 初始化客户端。 Args: primary_endpoint: 主集群Xinference地址。 secondary_endpoint: 备集群Xinference地址。 model_uid: 启动的模型UID。 redis_host: Redis主机地址。 redis_port: Redis端口。 redis_db: Redis数据库编号。 self.primary_endpoint primary_endpoint.rstrip(/) self.secondary_endpoint secondary_endpoint.rstrip(/) self.model_uid model_uid self.current_endpoint self.primary_endpoint # 当前使用的端点 self.is_primary_healthy True # 主集群健康状态 # 初始化Redis连接用于持久化向量数据 try: self.redis_client redis.Redis(hostredis_host, portredis_port, dbredis_db, decode_responsesTrue) self.redis_client.ping() logger.info(Redis连接成功。) except redis.ConnectionError as e: logger.error(f无法连接Redis: {e}) self.redis_client None # 健康检查配置 self.health_check_interval 30 # 健康检查间隔(秒) self.failure_threshold 3 # 连续失败次数阈值 self.failure_count 0 # 当前连续失败计数 def _generate_with_fallback(self, texts: List[str], endpoint: str) - Optional[List[List[float]]]: 向指定端点发送生成嵌入向量的请求。 url f{endpoint}/v1/embeddings payload { model: self.model_uid, input: texts } try: response requests.post(url, jsonpayload, timeout30) # 设置超时 response.raise_for_status() data response.json() embeddings [item[embedding] for item in data[data]] logger.info(f成功从 {endpoint} 获取 {len(embeddings)} 个向量的嵌入。) return embeddings except requests.exceptions.RequestException as e: logger.warning(f请求 {endpoint} 失败: {e}) return None def _save_to_redis(self, text: str, embedding: List[float]): 将文本和对应的向量保存到Redis。使用文本的哈希值作为键的一部分避免键过长。 if not self.redis_client: logger.warning(Redis客户端未初始化跳过数据持久化。) return import hashlib # 为文本生成一个简短的键名 text_hash hashlib.md5(text.encode(utf-8)).hexdigest()[:8] key fembedding:tao8k:{text_hash} value { text: text, embedding: embedding, timestamp: time.time() } try: # 使用hash结构存储 self.redis_client.hset(key, mappingvalue) # 设置过期时间例如30天可根据业务调整 self.redis_client.expire(key, 30*24*3600) logger.debug(f向量数据已保存到Redis: {key}) except Exception as e: logger.error(f保存数据到Redis失败: {e}) def embed(self, texts: List[str]) - List[List[float]]: 生成文本的嵌入向量支持主备容错并持久化结果。 Args: texts: 待编码的文本列表。 Returns: 嵌入向量列表与输入文本顺序一致。 all_embeddings [] # 策略1: 优先使用当前端点初始为主集群 logger.info(f尝试从当前端点 [{self.current_endpoint}] 获取嵌入...) embeddings self._generate_with_fallback(texts, self.current_endpoint) # 策略2: 如果当前端点失败且当前是主集群则尝试备集群 if embeddings is None: if self.current_endpoint self.primary_endpoint: logger.warning(主集群请求失败尝试切换到备集群...) self.is_primary_healthy False self.failure_count 1 # 检查是否达到故障阈值触发切换 if self.failure_count self.failure_threshold: logger.error(f主集群连续失败{self.failure_count}次执行切换。) self.current_endpoint self.secondary_endpoint self.failure_count 0 # 重置计数器 # 尝试从备集群获取 embeddings self._generate_with_fallback(texts, self.secondary_endpoint) if embeddings is not None: logger.info(已成功从备集群获取嵌入。) else: # 备集群也失败抛出异常 raise Exception(主备集群均无法提供服务。) else: # 当前已经是备集群且失败 raise Exception(备集群服务失败。) else: # 当前端点成功 if self.current_endpoint self.primary_endpoint: # 主集群成功重置失败计数 self.failure_count 0 if not self.is_primary_healthy: logger.info(主集群恢复健康。) self.is_primary_healthy True all_embeddings embeddings # 数据持久化将结果写入Redis (这里简化处理实际可批量) for text, emb in zip(texts, embeddings): self._save_to_redis(text, emb) return all_embeddings def health_check(self): 对主集群进行健康检查用于后台定时任务。 check_url f{self.primary_endpoint}/v1/models try: resp requests.get(check_url, timeout5) if resp.status_code 200: models resp.json().get(data, []) # 检查我们的模型是否在列表中 model_uids [m.get(id) for m in models] if self.model_uid in model_uids: if not self.is_primary_healthy: logger.info(健康检查: 主集群已恢复。) self.is_primary_healthy True self.failure_count 0 # 可以设置一个更保守的策略不立即切回主集群 return True # 检查失败 self.is_primary_healthy False logger.warning(健康检查: 主集群异常。) return False except Exception as e: logger.warning(f健康检查请求失败: {e}) self.is_primary_healthy False return False # 使用示例 if __name__ __main__: # 初始化客户端 client Tao8kEmbeddingClient( primary_endpointhttp://192.168.1.100:9997, secondary_endpointhttp://192.168.1.101:9997, model_uidtao-8k-embedding, # 请确保与启动的模型UID一致 redis_host192.168.1.102, # 假设Redis部署在另一台机器 redis_port6379 ) # 执行嵌入请求 texts_to_embed [什么是机器学习, 深度学习是机器学习的一个子领域。] try: vectors client.embed(texts_to_embed) print(f成功生成 {len(vectors)} 个向量维度: {len(vectors[0]) if vectors else 0}) except Exception as e: print(f嵌入失败: {e})4.2 关键逻辑解析智能路由与降级embed方法首先尝试当前端点默认主集群。如果失败它会增加失败计数。当连续失败达到阈值时客户端将current_endpoint切换为备集群的地址实现客户端侧的自适应降级。数据双写持久化一旦从某个集群成功获取向量_save_to_redis方法会立即将文本-向量对存储到Redis中。这里使用文本的MD5哈希值作为键避免存储长文本键。存储结构包含了文本、向量和时间戳。健康检查health_check方法可以作为一个后台定时任务运行定期探测主集群的/v1/models端点检查目标模型是否可用。如果发现主集群恢复可以更新状态为将来切回主集群做准备切换回主策略可以更复杂如手动确认。外部存储选择示例使用了Redis因为它性能高、数据结构丰富。对于更严格的数据持久化需求可以考虑PostgreSQL pgvector插件关系型保证支持复杂查询。MySQL通用性强。对象存储如MinIO/S3适合存储海量、低频访问的向量快照。消息队列如Kafka作为异步双写的缓冲通道。5. 部署、测试与运维建议方案实现后如何部署到生产环境并稳定运行这里给出一些关键步骤和建议。5.1 部署流程基础设施准备确保主、备服务器及Redis服务器网络互通防火墙开放相应端口9997, 6379。服务部署按照第2节在主备服务器上分别部署Xinference和启动tao-8k模型。配置负载均衡器可选但推荐在Nginx或云负载均衡器上配置两个后端主:9997 备:9997并设置健康检查路径为/v1/models。这样流量切换可以由更专业的网络设备完成比客户端降级更彻底。部署客户端SDK将封装好的Tao8kEmbeddingClient集成到你的业务应用中并配置好主备端点地址和Redis连接信息。初始化数据同步如果需要如果切换时备集群需要历史向量数据可以编写一个脚本从Redis或主存储中读取所有历史数据并模拟一次嵌入请求发送给备集群使其内部缓存或预热。注意Xinference本身可能不持久化模型内部状态所以历史数据主要靠外部存储。5.2 故障切换模拟测试测试是验证灾备方案有效性的唯一标准。模拟主集群宕机# 在主机A上停止Xinference服务 pkill -f xinference-local观察客户端日志持续向客户端发送嵌入请求。你应该会看到客户端日志显示主集群请求失败失败计数增加最终触发切换并从备集群成功获取结果。验证数据持久化连接Redis检查是否成功写入了新的向量数据。redis-cli -h 192.168.1.102 127.0.0.1:6379 KEYS embedding:tao8k:*模拟主集群恢复# 在主机A上重新启动Xinference xinference-local --host 0.0.0.0 --port 9997 # 重新注册启动模型如果进程完全重启 xinference launch --model-name tao-8k --model-type embedding ...观察健康检查与回切客户端的健康检查任务应检测到主集群恢复。你可以根据策略决定是否以及何时将current_endpoint切回主集群。生产环境中回切通常需要手动确认或在业务低峰期进行。5.3 运维监控建议监控指标服务可用性对主备集群的/v1/embeddings端点进行定时拨测。服务性能记录每次嵌入请求的耗时P50, P99。数据同步状态监控Redis的写入延迟、内存使用量。客户端状态监控客户端实例的当前端点、主集群健康状态、失败计数。告警设置主集群连续不可用超过阈值。备集群被激活。Redis连接失败或容量告急。嵌入请求平均耗时异常升高。定期演练定期如每季度执行一次完整的故障切换演练确保流程顺畅团队熟悉应急预案。6. 总结通过构建“主备Xinference集群 向量数据双写同步”的灾备方案我们为tao-8kEmbedding服务打造了一个具备高可用性和数据可靠性的生产级架构。这个方案的优势在于它的清晰性和实用性。主备服务实现了业务连续性外部共享存储保证了数据持久性两者结合构成了稳健的防线。文中提供的客户端代码和部署建议可以直接作为你项目实施的起点。当然没有银弹。这个方案引入了额外的复杂度需要维护多个节点和Redis和轻微的性能开销双写。但在大多数对服务稳定性有要求的场景下这种投入是值得的。你可以根据业务的实际SLA要求和资源情况对此方案进行裁剪或增强例如引入哨兵模式、更精细化的流量灰度策略等。希望这份详细的方案能帮助你构建出更强大、更可靠的AI服务基础设施。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。
tao-8k Embedding服务灾备方案:主备Xinference集群+向量数据双写同步
tao-8k Embedding服务灾备方案主备Xinference集群向量数据双写同步在构建基于大模型的应用时Embedding服务的稳定性和数据可靠性是核心命脉。想象一下你的智能问答系统、推荐引擎或文档检索功能因为一个Embedding服务节点宕机导致所有向量化能力瞬间瘫痪或者因为数据丢失让辛苦积累的语义知识库毁于一旦。这种风险是任何严肃的生产系统都无法承受的。今天我们就来深入探讨一个为tao-8kEmbedding模型量身打造的高可用灾备方案。这个方案的核心思想很简单不把鸡蛋放在一个篮子里。我们将通过部署主备两套Xinference集群并实现向量数据的双写同步来确保服务永不中断、数据永不丢失。无论你是正在规划生产环境的架构师还是希望提升现有服务健壮性的开发者这套清晰、可落地的方案都能为你提供直接的参考。1. 方案全景与核心价值在深入技术细节之前让我们先俯瞰整个方案的架构理解它究竟解决了什么问题。1.1 我们要解决什么痛点单一节点的Embedding服务主要面临两大风险服务中断风险硬件故障、软件崩溃、网络问题或日常维护都可能导致服务不可用进而使所有依赖向量化的上游应用功能失效。数据丢失风险生成的向量数据如果仅存储在内存或单个节点上一旦服务重启或节点失效历史向量数据将荡然无存需要重新生成耗时耗力。1.2 方案核心主备集群与双写同步我们的灾备方案通过两个关键设计来应对上述风险主备Xinference集群部署两套独立的Xinference服务一主一备。平时由主集群提供服务备集群处于热备状态。当主集群发生故障时流量可以快速、自动或手动切换到备集群实现服务的高可用。向量数据双写同步任何文本生成向量的请求都会同时发送给主备两套集群或先写主再异步同步至备。生成的向量数据会持久化到共享的外部存储如Redis、数据库、对象存储中。这样即使某个集群完全宕机另一个集群也能从共享存储中获取历史向量数据保证数据的连续性和一致性。这个方案带来的核心价值是服务高可用具备故障自动/手动切换能力极大提升SLA服务等级协议。数据可靠性向量数据持久化且多副本避免丢失。可扩展性架构为未来水平扩展多个推理节点奠定了基础。维护友好可以在不影响业务的情况下对任一集群进行升级或维护。2. 基础环境搭建部署主备tao-8k服务灾备方案建立在稳定运行的服务之上。我们首先需要在两台独立的服务器上部署主、备两个Xinference集群并加载tao-8kEmbedding模型。2.1 准备工作假设我们有两台服务器主机A主集群IP192.168.1.100主机B备集群IP192.168.1.101确保两台服务器均满足Python 3.8 环境足够的磁盘空间用于存放模型tao-8k模型约几个GB网络互通后续需要同步数据2.2 在两台主机上部署Xinference并启动tao-8k在主备两台机器上执行相同的部署操作。步骤1安装Xinferencepip install xinference[all]步骤2启动Xinference服务默认会在localhost:9997启动。为了能从其他机器访问我们指定绑定IP。# 在主机A上执行 xinference-local --host 0.0.0.0 --port 9997 # 在主机B上执行 xinference-local --host 0.0.0.0 --port 9997--host 0.0.0.0表示监听所有网络接口。步骤3通过命令行注册并启动tao-8k模型我们需要使用Xinference的客户端来注册模型。模型文件已预置在/usr/local/bin/AI-ModelScope/tao-8k。# 首先获取Xinference的客户端 xinference-client # 注册并启动tao-8k embedding模型 # 这里假设模型类型为 embedding模型格式为 ggufv2请根据实际模型格式调整。 # 我们为模型起一个唯一标识例如 tao-8k-embedding xinference launch --model-name tao-8k --model-type embedding --model-format ggufv2 --model-path /usr/local/bin/AI-ModelScope/tao-8k --replica 1关键参数解释--model-name: 自定义的模型名称用于后续调用。--model-type: 模型类型tao-8k是嵌入模型所以是embedding。--model-format: 模型文件格式需根据实际情况指定如ggufv2,pytorch等。--model-path:模型在本地的绝对路径即/usr/local/bin/AI-ModelScope/tao-8k。--replica: 副本数设置为1。步骤4验证服务启动成功部署完成后可以通过查看日志或Web UI验证。# 查看Xinference日志日志路径可能因启动方式而异 tail -f /root/workspace/xinference.log在日志中寻找模型加载成功的提示。同时你可以通过浏览器分别访问主集群Web UI:http://192.168.1.100:9997备集群Web UI:http://192.168.1.101:9997在Web UI的“已启动模型”列表中应该能看到tao-8k-embedding模型处于运行状态。至此主备两套独立的tao-8kEmbedding服务已经准备就绪。3. 灾备架构设计与数据流有了两个服务节点下一步是设计如何让它们协同工作并确保数据安全。下面是整个灾备方案的核心架构图与数据流说明。[上游应用] (如RAG系统、推荐系统) | | HTTP请求 (文本) v [负载均衡/网关] (如Nginx, API Gateway) | |-------------------[故障检测]------------------- | | v (正常流量) v (主库故障时) [主 Xinference 集群] [备 Xinference 集群] (192.168.1.100:9997) (192.168.1.101:9997) | | |--(1. 生成向量 双写)--------------------------| | | v v [外部共享存储] -----------------------------(2. 数据同步)---| (Redis / PostgreSQL / 对象存储) | | | |------------------[3. 数据读取]--------------------| | v [向量数据库] (如Milvus, Qdrant, Weaviate)数据流详解双写请求上游应用通过负载均衡器将生成嵌入向量的请求发送到当前主集群。应用端SDK或一个中间件组件在收到主集群成功响应后异步地将同一请求发送给备集群或者采用更可靠的方式将主集群返回的向量结果直接写入外部共享存储。数据同步我们不直接依赖两个Xinference集群之间的点对点同步。而是通过“双写”或“先写主存储再同步至备存储”的模式将生成的(文本, 向量)对持久化到如Redis、关系型数据库或对象存储中。备集群在启动或需要时可以从这个共享存储中读取数据。故障切换负载均衡器或网关集成健康检查定期探测主集群的/v1/embeddings端点。当主集群连续失败多次则自动将流量路由到备集群。切换后备集群承担所有新的向量生成请求并从共享存储中读取历史向量数据保证业务连续性。向量存储生成的向量最终会被索引到专业的向量数据库如Milvus中用于后续的相似性检索。向量数据库的数据源来自共享存储确保了数据源的唯一性和一致性。关键点这个设计的精髓在于解耦。服务高可用主备切换和数据可靠性外部存储由不同的组件负责架构更清晰容错能力更强。4. 核心实现客户端双写与数据持久化现在我们来编写最关键的部分一个智能的客户端它负责与主备集群通信并实现向量数据的双写与持久化。我们将创建一个Python类Tao8kEmbeddingClient它具备以下能力维护主备集群的终端地址。优先调用主集群失败时自动重试并切换至备集群。将成功生成的向量数据写入外部存储这里以Redis为例。4.1 客户端实现代码import requests import json import time import logging from typing import List, Optional, Dict, Any import redis # 需要 pip install redis logging.basicConfig(levellogging.INFO) logger logging.getLogger(__name__) class Tao8kEmbeddingClient: tao-8k Embedding高可用客户端支持主备切换与数据双写。 def __init__(self, primary_endpoint: str http://192.168.1.100:9997, secondary_endpoint: str http://192.168.1.101:9997, model_uid: str tao-8k-embedding, # 与启动模型时指定的名称一致 redis_host: str localhost, redis_port: int 6379, redis_db: int 0): 初始化客户端。 Args: primary_endpoint: 主集群Xinference地址。 secondary_endpoint: 备集群Xinference地址。 model_uid: 启动的模型UID。 redis_host: Redis主机地址。 redis_port: Redis端口。 redis_db: Redis数据库编号。 self.primary_endpoint primary_endpoint.rstrip(/) self.secondary_endpoint secondary_endpoint.rstrip(/) self.model_uid model_uid self.current_endpoint self.primary_endpoint # 当前使用的端点 self.is_primary_healthy True # 主集群健康状态 # 初始化Redis连接用于持久化向量数据 try: self.redis_client redis.Redis(hostredis_host, portredis_port, dbredis_db, decode_responsesTrue) self.redis_client.ping() logger.info(Redis连接成功。) except redis.ConnectionError as e: logger.error(f无法连接Redis: {e}) self.redis_client None # 健康检查配置 self.health_check_interval 30 # 健康检查间隔(秒) self.failure_threshold 3 # 连续失败次数阈值 self.failure_count 0 # 当前连续失败计数 def _generate_with_fallback(self, texts: List[str], endpoint: str) - Optional[List[List[float]]]: 向指定端点发送生成嵌入向量的请求。 url f{endpoint}/v1/embeddings payload { model: self.model_uid, input: texts } try: response requests.post(url, jsonpayload, timeout30) # 设置超时 response.raise_for_status() data response.json() embeddings [item[embedding] for item in data[data]] logger.info(f成功从 {endpoint} 获取 {len(embeddings)} 个向量的嵌入。) return embeddings except requests.exceptions.RequestException as e: logger.warning(f请求 {endpoint} 失败: {e}) return None def _save_to_redis(self, text: str, embedding: List[float]): 将文本和对应的向量保存到Redis。使用文本的哈希值作为键的一部分避免键过长。 if not self.redis_client: logger.warning(Redis客户端未初始化跳过数据持久化。) return import hashlib # 为文本生成一个简短的键名 text_hash hashlib.md5(text.encode(utf-8)).hexdigest()[:8] key fembedding:tao8k:{text_hash} value { text: text, embedding: embedding, timestamp: time.time() } try: # 使用hash结构存储 self.redis_client.hset(key, mappingvalue) # 设置过期时间例如30天可根据业务调整 self.redis_client.expire(key, 30*24*3600) logger.debug(f向量数据已保存到Redis: {key}) except Exception as e: logger.error(f保存数据到Redis失败: {e}) def embed(self, texts: List[str]) - List[List[float]]: 生成文本的嵌入向量支持主备容错并持久化结果。 Args: texts: 待编码的文本列表。 Returns: 嵌入向量列表与输入文本顺序一致。 all_embeddings [] # 策略1: 优先使用当前端点初始为主集群 logger.info(f尝试从当前端点 [{self.current_endpoint}] 获取嵌入...) embeddings self._generate_with_fallback(texts, self.current_endpoint) # 策略2: 如果当前端点失败且当前是主集群则尝试备集群 if embeddings is None: if self.current_endpoint self.primary_endpoint: logger.warning(主集群请求失败尝试切换到备集群...) self.is_primary_healthy False self.failure_count 1 # 检查是否达到故障阈值触发切换 if self.failure_count self.failure_threshold: logger.error(f主集群连续失败{self.failure_count}次执行切换。) self.current_endpoint self.secondary_endpoint self.failure_count 0 # 重置计数器 # 尝试从备集群获取 embeddings self._generate_with_fallback(texts, self.secondary_endpoint) if embeddings is not None: logger.info(已成功从备集群获取嵌入。) else: # 备集群也失败抛出异常 raise Exception(主备集群均无法提供服务。) else: # 当前已经是备集群且失败 raise Exception(备集群服务失败。) else: # 当前端点成功 if self.current_endpoint self.primary_endpoint: # 主集群成功重置失败计数 self.failure_count 0 if not self.is_primary_healthy: logger.info(主集群恢复健康。) self.is_primary_healthy True all_embeddings embeddings # 数据持久化将结果写入Redis (这里简化处理实际可批量) for text, emb in zip(texts, embeddings): self._save_to_redis(text, emb) return all_embeddings def health_check(self): 对主集群进行健康检查用于后台定时任务。 check_url f{self.primary_endpoint}/v1/models try: resp requests.get(check_url, timeout5) if resp.status_code 200: models resp.json().get(data, []) # 检查我们的模型是否在列表中 model_uids [m.get(id) for m in models] if self.model_uid in model_uids: if not self.is_primary_healthy: logger.info(健康检查: 主集群已恢复。) self.is_primary_healthy True self.failure_count 0 # 可以设置一个更保守的策略不立即切回主集群 return True # 检查失败 self.is_primary_healthy False logger.warning(健康检查: 主集群异常。) return False except Exception as e: logger.warning(f健康检查请求失败: {e}) self.is_primary_healthy False return False # 使用示例 if __name__ __main__: # 初始化客户端 client Tao8kEmbeddingClient( primary_endpointhttp://192.168.1.100:9997, secondary_endpointhttp://192.168.1.101:9997, model_uidtao-8k-embedding, # 请确保与启动的模型UID一致 redis_host192.168.1.102, # 假设Redis部署在另一台机器 redis_port6379 ) # 执行嵌入请求 texts_to_embed [什么是机器学习, 深度学习是机器学习的一个子领域。] try: vectors client.embed(texts_to_embed) print(f成功生成 {len(vectors)} 个向量维度: {len(vectors[0]) if vectors else 0}) except Exception as e: print(f嵌入失败: {e})4.2 关键逻辑解析智能路由与降级embed方法首先尝试当前端点默认主集群。如果失败它会增加失败计数。当连续失败达到阈值时客户端将current_endpoint切换为备集群的地址实现客户端侧的自适应降级。数据双写持久化一旦从某个集群成功获取向量_save_to_redis方法会立即将文本-向量对存储到Redis中。这里使用文本的MD5哈希值作为键避免存储长文本键。存储结构包含了文本、向量和时间戳。健康检查health_check方法可以作为一个后台定时任务运行定期探测主集群的/v1/models端点检查目标模型是否可用。如果发现主集群恢复可以更新状态为将来切回主集群做准备切换回主策略可以更复杂如手动确认。外部存储选择示例使用了Redis因为它性能高、数据结构丰富。对于更严格的数据持久化需求可以考虑PostgreSQL pgvector插件关系型保证支持复杂查询。MySQL通用性强。对象存储如MinIO/S3适合存储海量、低频访问的向量快照。消息队列如Kafka作为异步双写的缓冲通道。5. 部署、测试与运维建议方案实现后如何部署到生产环境并稳定运行这里给出一些关键步骤和建议。5.1 部署流程基础设施准备确保主、备服务器及Redis服务器网络互通防火墙开放相应端口9997, 6379。服务部署按照第2节在主备服务器上分别部署Xinference和启动tao-8k模型。配置负载均衡器可选但推荐在Nginx或云负载均衡器上配置两个后端主:9997 备:9997并设置健康检查路径为/v1/models。这样流量切换可以由更专业的网络设备完成比客户端降级更彻底。部署客户端SDK将封装好的Tao8kEmbeddingClient集成到你的业务应用中并配置好主备端点地址和Redis连接信息。初始化数据同步如果需要如果切换时备集群需要历史向量数据可以编写一个脚本从Redis或主存储中读取所有历史数据并模拟一次嵌入请求发送给备集群使其内部缓存或预热。注意Xinference本身可能不持久化模型内部状态所以历史数据主要靠外部存储。5.2 故障切换模拟测试测试是验证灾备方案有效性的唯一标准。模拟主集群宕机# 在主机A上停止Xinference服务 pkill -f xinference-local观察客户端日志持续向客户端发送嵌入请求。你应该会看到客户端日志显示主集群请求失败失败计数增加最终触发切换并从备集群成功获取结果。验证数据持久化连接Redis检查是否成功写入了新的向量数据。redis-cli -h 192.168.1.102 127.0.0.1:6379 KEYS embedding:tao8k:*模拟主集群恢复# 在主机A上重新启动Xinference xinference-local --host 0.0.0.0 --port 9997 # 重新注册启动模型如果进程完全重启 xinference launch --model-name tao-8k --model-type embedding ...观察健康检查与回切客户端的健康检查任务应检测到主集群恢复。你可以根据策略决定是否以及何时将current_endpoint切回主集群。生产环境中回切通常需要手动确认或在业务低峰期进行。5.3 运维监控建议监控指标服务可用性对主备集群的/v1/embeddings端点进行定时拨测。服务性能记录每次嵌入请求的耗时P50, P99。数据同步状态监控Redis的写入延迟、内存使用量。客户端状态监控客户端实例的当前端点、主集群健康状态、失败计数。告警设置主集群连续不可用超过阈值。备集群被激活。Redis连接失败或容量告急。嵌入请求平均耗时异常升高。定期演练定期如每季度执行一次完整的故障切换演练确保流程顺畅团队熟悉应急预案。6. 总结通过构建“主备Xinference集群 向量数据双写同步”的灾备方案我们为tao-8kEmbedding服务打造了一个具备高可用性和数据可靠性的生产级架构。这个方案的优势在于它的清晰性和实用性。主备服务实现了业务连续性外部共享存储保证了数据持久性两者结合构成了稳健的防线。文中提供的客户端代码和部署建议可以直接作为你项目实施的起点。当然没有银弹。这个方案引入了额外的复杂度需要维护多个节点和Redis和轻微的性能开销双写。但在大多数对服务稳定性有要求的场景下这种投入是值得的。你可以根据业务的实际SLA要求和资源情况对此方案进行裁剪或增强例如引入哨兵模式、更精细化的流量灰度策略等。希望这份详细的方案能帮助你构建出更强大、更可靠的AI服务基础设施。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。