MongoDB 4.2——分片简介
分片简介1、什么是分片2、理解集群组件3、在单机集群上进行分片1、什么是分片分片是指跨机器拆分数据的过程有时也会用术语分区partitioning来表示这个概念。通过在每台机器上放置数据的子集无须功能强大的机器只使用大量功能稍弱的机器就可以存储更多的数据并处理更多的负载。分片还可以用于其他目的包括将经常访问的数据放置在更高性能的硬件上或基于地理位置比如基于在一个特定语言环境下的用户来拆分集合中的文档以使它们接近最常对其进行访问的应用程序服务器。大部分数据库软件支持进行手动分片。使用这种方法应用程序会维护到多个不同数据库服务器端的连接每个服务器端都是完全独立的。应用程序不仅管理不同服务器上不同数据的存储还管理在适当的服务器上查询数据。这种方式可以很好地工作但当从集群中添加或删除节点或者面对数据分布或负载模式的变化时就非常难以维护了。MongoDB 支持自动分片这种方式试图将数据库架构从应用程序中抽象出来并简化系统管理。在某种程度上MongoDB 允许应用程序好像始终在和一台单机的MongoDB 服务器对话一样。在运维方面MongoDB 可以自动均衡分片上的数据使容量的添加和删除变得更容易。无论从开发还是运维的角度来看分片都是最复杂的MongoDB 配置方式。有许多组件需要配置和监控数据在集群中会自动转移。在尝试部署或使用分片集群之前应该首先熟悉单机服务器和副本集。此外与副本集一样配置和部署分片集群的推荐方式是通过 MongoDBOps Manager 或 MongoDB Atlas。如果需要保留对计算基础设施的控制建议使用 Ops Manager。如果可以 将基础设施管理留给 MongoDB可以选择在 Amazon AWS、Microsoft Azure 或 Google Compute Cloud 中运行​则推荐使用 MongoDB Atlas。2、理解集群组件MongoDB 的分片机制允许你创建一个由许多机器分片组成的集群并将集合中的数据分散在集群中在每个分片上放置数据的一个子集。这允许应用程序超出单机服务器或副本集的资源限制。许多人对复制和分片之间的区别感到困惑。记住复制在多台服务器上创建了数据的精确副本因此每台服务器都是其他服务器的镜像。相反每个分片包含了不同的数据子集。分片的目标之一是使由两个、3 个、10 个甚至数百个分片组成的集群对应用程序来说就像是一台单机服务器。为了对应用程序隐藏这些细节需要在分片前面运行一个或多个称为 mongos 的路由进程。mongos 维护着一个“目录”​指明了哪个分片包含哪些数据。如上图所示应用程序可以正常连接到此路由服务器并发出请求。路由服务器知道哪些数据在哪个分片上可以将请求转发到适当的分片。如果有对请求的响应路由服务器会收集它们并在必要时进行合并然后再发送回应用程序。对应用程序来说它只知道自己连接到了一个单独的mongod如下图所示。3、在单机集群上进行分片在单台机器上快速建立一个集群。首先使用 --nodb和 --norc 选项启动 mongo shell$ mongo--nodb--norc使用 ShardingTest 类创建集群。在刚启动的 mongoshell 中运行以下代码stShardingTest({name:one-min-shards,chunkSize:1,shards:2,rs:{nodes:3,oplogSize:10},other:{enableBalancer:true}});chunksize 选项会在后面行介绍。目前只需将其设置为 1。至于其他传递给 ShardingTest 的选项name仅仅是分片集群的一个标签shards 指定了集群将由两个分片组成在本例中这样做是为了保持较低的资源需求​rs 将每个分片定义为一组 3 个节点的副本集其oplogSize 为 10MiB同样保持较低的资源占用​。虽然可以为每个分片仅运行一个单独的 mongod 进程但是以副本集创建每个分片可以将典型的分片集群架构描绘得更加清晰。在最后一个选项中我们指示ShardingTest 在集群启动后启用均衡器。这可以确保数据均匀分布在两个分片上。ShardingTest 是 MongoDB 工程师为内部使用而设计的一个类因此没有外部文档。但是由于附带在了MongoDB 服务器端的程序中因此它提供了一个使用分 片集群的最直接方法。ShardingTest 最初是为支持服务器端测试套件而设计的现在仍然用于此目的。默认情况下它在保持尽可能低的资源占用以及建立体系结构相对复杂的分片集群方面提供了许多便利。它假设你的机器上存在 /data/db 目录如果 ShardingTest 运行失败则需要创建该目录然后重新运行命令。当运行这个命令时ShardingTest 会为你自动做很多事情。它会创建一个包含两个分片的集群每个分片都是一个副本集。同时会对副本集进行配置并使用必要的选项启动每个节点以建立复制协议。它会启动一个 mongos来管理跨分片的请求这样客户端就可以像与一个独立的mongod 通信一样与集群进行交互。最后它会为用于维护路由表信息的配置服务器启动一个额外的副本集以确保查询被定向到正确的分片。记住分片的主要使用场景是拆分数据集以解决硬件和成本的限制或为应用程序提 供更好的性能比如地理分区​。MongoDB 分片以一种与应用程序在许多方面无缝对接的方式提供了这些功能。当 ShardingTest 完成集群设置后将启动并运行 10 个进程你可以连接到这些进程两个副本集各有 3 个节点​、一个配置服务器副本集有 3 个节点​以及一个 mongos。默认情况下这些进程会从 20000 端口开始。mongos 会运行在 20009 端口上。在本地机器上运行的其他进程以及之前对 ShardingTest 的调用可能会影响 ShardingTest 使用的端口但是确定集群进程运行在哪些端口上应该不会有什么困难。接下来会连接到 mongos 来使用集群。整个集群会将日志转储到当前 shell 中因此打开第二个终端窗口并启动另一个 mongo shell$ mongo--nodb使用这个 shell 连接到集群的 mongos。再次说明你的mongos 应该运行在 20009 端口上db(newMongo(localhost:20009)).getDB(accounts)注意mongo shell 中的提示符应该发生变化以反映出已经连接到一个 mongos。shell 作为客户端连接到了 mongos。可以开始向mongos 发送请求了它会将请求路由到相应的分片。你不需要知道任何关于分片的信息比如有多少个分片或者它们的地址是什么。只要有分片存在就可以将请求发送给 mongos并允许其转发到合适的分片上。首先插入一些数据for(vari0;i100000;i){db.users.insert({username:useri,created_at:newDate()});}db.users.count()100000可以看到与 mongos 的交互与使用单机服务器是一样的。可以运行 sh.status() 来获得集群的总体视图。此命令会提供一个分片、数据库以及集合的摘要。sh.status()---Sharding Status---sharding version:{_id:1,minCompatibleVersion:5,currentVersion:6,clusterId:ObjectId(5a4f93d6bcde690005986071)}shards:{_id:one-min-shards-rs0,host:one-min-shards-rs0/MBP:20000,MBP:20001,MBP:20002,state:1}{_id:one-min-shards-rs1,host:one-min-shards-rs1/MBP:20003,MBP:20004,MBP:20005,state:1}active mongoses:3.6.1:1autosplit:Currently enabled:nobalancer:Currently enabled:no Currently running:no Failed balancer roundsinlast5attempts:0Migration Resultsforthe last24hours:No recent migrationsdatabases:{_id:accounts,primary:one-min-shards-rs1,partitioned:false}{_id:config,primary:config,partitioned:true}config.system.sessions shard key:{_id:1}unique:falsebalancing:truechunks:one-min-shards-rs01{_id:{$minKey:1}}--{_id:{$maxKey:1}}on:one-min-shards-rs0Timestamp(1,0)sh 类似于 rs但它是用于分片的这是一个全局变量定义了许多关于分片的辅助函数可以通过运行sh.help() 进行查看。正如 sh.status() 的输出所示当前有两个分片和两个数据库config 数据库是自动创建的​。你的 accounts 数据库的主分片primary shard可能与这里显示的不同。主分片是为每个数据库随机选择的一个“主基地”​。所有的数据都会在这个主分片上。MongoDB 现在还不能自动分发数据因为它不知道你希望如何或者是否进行分发。你必须明确指定在每个集合中应该如何分布数据。主分片与副本集的主节点不同。主分片是指组成某个分片的整个副本集。副本集中的主节点是集合中可以接收写操作的单台服务器。要对一个特定的集合进行分片首先需要在集合的数据库上启用分片。如下所示运行 enableSharding 命令sh.enableSharding(accounts)现在可以对 accounts 数据库中的集合进行分片了。在对集合进行分片时需要选择一个片键shardkey​。片键是 MongoDB 用来拆分数据的一个或几个字段。如果选择在 “username” 字段上分片MongoDB 就 会根据用户名的范围对数据进行拆分“a1-steak-sauce” 到 “defcon”、“defcon1” 到 “howie1998”等等。可以将选择一个片键看作为集合中的数据选择一个排列顺序。这与索引的概念类似也十分合理随着集合的增大片键会成为集合中最重要的索引。只有创建了索引的字段才能够作为片键。因此在启用分片之前必须在想要分片的键上创建一个索引db.users.createIndex({username:1})现在可以通过 “username” 来对集合进行分片了sh.shardCollection(accounts.users,{username:1})尽管这里在选择片键时没有做太多考虑但在实际系统中这是一个需要仔细斟酌的重要决定。等待几分钟并再次运行 sh.status()可以看到比之前显示出了更多的信息sh.status()---Sharding Status---sharding version:{_id:1,minCompatibleVersion:5,currentVersion:6,clusterId:ObjectId(5a4f93d6bcde690005986071)}shards:{_id:one-min-shards-rs0,host:one-min-shards-rs0/MBP:20000,MBP:20001,MBP:20002,state:1}{_id:one-min-shards-rs1,host:one-min-shards-rs1/MBP:20003,MBP:20004,MBP:20005,state:1}active mongoses:3.6.1:1autosplit:Currently enabled:nobalancer:Currently enabled:yes Currently running:no Failed balancer roundsinlast5attempts:0Migration Resultsforthe last24hours:6:Successdatabases:{_id:accounts,primary:one-min-shards-rs1,partitioned:true}accounts.users shard key:{username:1}unique:falsebalancing:truechunks:one-min-shards-rs06one-min-shards-rs17{username:{$minKey:1}}--{username:user17256}on:one-min-shards-rs0Timestamp(2,0){username:user17256}--{username:user24515}on:one-min-shards-rs0Timestamp(3,0){username:user24515}--{username:user31775}on:one-min-shards-rs0Timestamp(4,0){username:user31775}--{username:user39034}on:one-min-shards-rs0Timestamp(5,0){username:user39034}--{username:user46294}on:one-min-shards-rs0Timestamp(6,0){username:user46294}--{username:user53553}on:one-min-shards-rs0Timestamp(7,0){username:user53553}--{username:user60812}on:one-min-shards-rs1Timestamp(7,1){username:user60812}--{username:user68072}on:one-min-shards-rs1Timestamp(1,7){username:user68072}--{username:user75331}on:one-min-shards-rs1Timestamp(1,8){username:user75331}--{username:user82591}on:one-min-shards-rs1Timestamp(1,9){username:user82591}--{username:user89851}on:one-min-shards-rs1Timestamp(1,10){username:user89851}--{username:user9711}on:one-min-shards-rs1Timestamp(1,11){username:user9711}--{username:{$maxKey:1}}on:one-min-shards-rs1Timestamp(1,12){_id:config,primary:config,partitioned:true}config.system.sessions shard key:{_id:1}unique:falsebalancing:truechunks:one-min-shards-rs01{_id:{$minKey:1}}--{_id:{$maxKey:1}}on:one-min-shards-rs0Timestamp(1,0)这个集合被分成了 13 个块每个块是数据的一个子集。这些是按照片键范围排列的{“username” : minValue}– {“username” : maxValue} 表示每个数据块的范围​。查看输出信息的 “on” : shard 部分可以看到这些块均匀地分布在各个分片之间。将集合拆分成数据块的过程如图所示。在分片之前集合实际上是一个单独的块。分片根据片键将其拆分成更小的块。之后这些数据块可能会分布到集群中。注意块列表开始和结束处的键即$minKey和$maxKey。$minKey可以被认为是“负无穷”​。这个值比MongoDB 中的其他值都要小。类似地$maxKey相当于“正无穷”​。它比任何其他值都要大。因此总是会在块范围中看到这两个“极值”​。片键的值始终位于$minKey和$maxKey之间。这两个值实际上是 BSON 类型不应该用在应用程序中它们主要是供内部使用的。如果希 望在 shell 中引用它们可以使用 MinKey 和 MaxKey常量。现在数据已经分布在多个分片上了让我们尝试执行一些查询。首先查询一个特定的用户名db.users.find({username:user12345}){_id:ObjectId(5a4fb11dbb9ce6070f377880),username:user12345,created_at:ISODate(2018-01-05T17:08:45.657Z)}可以看到查询语句工作正常。现在执行一下 explain 来看看 MongoDB 在幕后是如何处理的db.users.find({username:user12345}}).explain(){queryPlanner:{mongosPlannerVersion:1,winningPlan:{stage:SINGLE_SHARD,shards:[{shardName:one-min-shards-rs0,connectionString:one-min-shards-rs0/MBP:20000,MBP:20001,MBP:20002,serverInfo:{host:MBP,port:20000,version:3.6.1,gitVersion:025d4f4fe61efd1fb6f0005be20cb45a004093d1},plannerVersion:1,namespace:accounts.users,indexFilterSet:false,parsedQuery:{username:{$eq:user12345}},winningPlan:{stage:FETCH,inputStage:{stage:SHARDING_FILTER,inputStage:{stage:IXSCAN,keyPattern:{username:1},indexName:username_1,isMultiKey:false,multiKeyPaths:{username:[]},isUnique:false,isSparse:false,isPartial:false,indexVersion:2,direction:forward,indexBounds:{username:[[\user12345\, \user12345\]]}}}},rejectedPlans:[]}]}},ok:1,$clusterTime:{clusterTime:Timestamp(1515174248,1),signature:{hash:BinData(0,AAAAAAAAAAAAAAAAAAAAAAAAAAA),keyId:NumberLong(0)}},operationTime:Timestamp(1515173700,201)}从 explain 输出的 “winningPlan” 字段中可以看到集群使用单个分片 (one-min-shards-rs0完成了这个查询。根据之前展示出来的 sh.status() 的输出可以看到user12345 确实属于集群中为该分片列出的第一个块的键范围。由于 “username” 是片键因此 mongos 能够将查询直接路由到正确的分片上。作为对比下面来看看查询所有用户的结果db.users.find().explain(){queryPlanner:{mongosPlannerVersion:1,winningPlan:{stage:SHARD_MERGE,shards:[{shardName:one-min-shards-rs0,connectionString:one-min-shards-rs0/MBP:20000,MBP:20001,MBP:20002,serverInfo:{host:MBP.fios-router.home,port:20000,version:3.6.1,gitVersion:025d4f4fe61efd1fb6f0005be20cb45a004093d1},plannerVersion:1,namespace:accounts.users,indexFilterSet:false,parsedQuery:{},winningPlan:{stage:SHARDING_FILTER,inputStage:{stage:COLLSCAN,direction:forward}},rejectedPlans:[]},{shardName:one-min-shards-rs1,connectionString:one-min-shards-rs1/MBP:20003,MBP:20004,MBP:20005,serverInfo:{host:MBP.fios-router.home,port:20003,version:3.6.1,gitVersion:025d4f4fe61efd1fb6f0005be20cb45a004093d1},plannerVersion:1,namespace:accounts.users,indexFilterSet:false,parsedQuery:{},winningPlan:{stage:SHARDING_FILTER,inputStage:{stage:COLLSCAN,direction:forward}},rejectedPlans:[]}]}},ok:1,$clusterTime:{clusterTime:Timestamp(1515174893,1),signature:{hash:BinData(0,AAAAAAAAAAAAAAAAAAAAAAAAAAA),keyId:NumberLong(0)}},operationTime:Timestamp(1515173709,514)}从这个 explain 中可以看到该查询必须访问两个分片才能找到所有数据。通常来说如果在查询中没有使用片键mongos 就不得不将查询发送到每个分片上。包含片键并可以发送到单个分片或分片子集的查询称为定向查询targeted query​。必须发送到所有分片的查询称为分散–收集查询scatter-gather query​也称为广播查询mongos 会将查询分散到所有分片然后再从各个分片收集结果。完成这个实验后就可以关闭副本集了。切换回原来的shell并按几次 Enter 键返回到命令行然后运行st.stop() 干净地关闭所有服务器st.stop()如果不确定某个操作的作用那么使用 ShardingTest 快速创建一个本地集群并尝试一下会很有帮助。

相关新闻

OpenAI宠物功能技术解析:AI社交化与个性化实现方案

OpenAI宠物功能技术解析:AI社交化与个性化实现方案

最近 OpenAI 的一个新功能在开发者圈子里引起了不小的讨论——宠物功能支持分享链接给好友收养。这听起来像是一个娱乐功能,但背后其实反映了 AI 产品正在从工具型向社交型转变的重要趋势。如果你以为这只是个简单的"养电子宠物"游戏,那就低估…

2026/7/28 2:37:08阅读更多 →
2004年文本分析项目需求与技术实现探讨

2004年文本分析项目需求与技术实现探讨

由于您提供的输入内容过于简略(仅包含"2004 Text 1"的标题,无正文、关键词和摘要描述),我无法生成符合要求的5000字专业博文。根据创作规范,我需要至少包含以下要素才能开始创作:项目正文&#x…

2026/7/28 2:37:08阅读更多 →
会议室预约管理系统开发与Java EE技术实践

会议室预约管理系统开发与Java EE技术实践

1. 会议室预约管理系统概述会议室预约管理系统是现代企业办公场景中的刚需工具,尤其适合作为计算机专业毕业设计的选题。这个系统本质上是一个基于B/S架构的Web应用,通过信息化手段解决传统纸质登记或口头预约带来的管理混乱问题。我参与过多个企业级会议…

2026/7/28 2:37:08阅读更多 →
告别豆腐块!Noto Emoji表情字体终极指南:让你的表情符号完美显示

告别豆腐块!Noto Emoji表情字体终极指南:让你的表情符号完美显示

告别豆腐块!Noto Emoji表情字体终极指南:让你的表情符号完美显示 【免费下载链接】noto-emoji Noto Emoji fonts 项目地址: https://gitcode.com/gh_mirrors/no/noto-emoji 你是否曾经遇到过这样的尴尬情况?在手机上精心挑选的表情符号…

2026/7/28 3:59:19阅读更多 →
影刀RPA完全指南:多账号管理与浏览器环境隔离策略

影刀RPA完全指南:多账号管理与浏览器环境隔离策略

影刀RPA完全指南:多账号管理与浏览器环境隔离策略 做跨境电商和电商运营的朋友,手上少则三五个多则几十个平台账号——拼多多、淘宝、TEMU、TikTok Shop、小红书,每个平台可能还不止一个。如果影刀RPA在同一个浏览器环境下切换账号登录&…

2026/7/28 3:59:19阅读更多 →
【大白话说Java面试题 第200题】【09_Zookeeper篇】第1题:ZooKeeper 是什么?

【大白话说Java面试题 第200题】【09_Zookeeper篇】第1题:ZooKeeper 是什么?

📌 PDF:大白话说Java面试题 — 09_Zookeeper篇 第1题:ZooKeeper 是什么? 📚 回答: 核心考点: ZooKeeper 是分布式系统的"协调中枢",大厂面试中不会只问"树形目录结…

2026/7/28 3:59:19阅读更多 →
【大白话说Java面试题 第199题】【08_Kafka篇】第15题:Kafka 的数据 Offset 读取流程是怎样的?

【大白话说Java面试题 第199题】【08_Kafka篇】第15题:Kafka 的数据 Offset 读取流程是怎样的?

📌 PDF:大白话说Java面试题 — 08_Kafka篇 第15题:Kafka 的数据 Offset 读取流程是怎样的? 📚 回答: 核心考点: Kafka 的 Offset 是消费者追踪消费进度的核心机制。大厂面试中,面试…

2026/7/28 3:59:19阅读更多 →
SQL性能突降排查实战:从CPU拉满到根因定位的完整指南

SQL性能突降排查实战:从CPU拉满到根因定位的完整指南

最近在技术社区看到一个很有意思的面试题,它没有问“索引怎么建”或者“SQL怎么写”,而是抛出了一个更贴近实战的场景:一条昨天还跑得飞快的SQL,今天突然慢如蜗牛,直接把数据库CPU拉满,你作为第一责任人&am…

2026/7/28 3:59:19阅读更多 →
基于LabVIEW与Arduino的蓝牙遥控智能车:通信协议与运动控制全解析

基于LabVIEW与Arduino的蓝牙遥控智能车:通信协议与运动控制全解析

1. 项目概述与核心思路上次我们聊了LabVIEW和Arduino联手打造智能车的硬件选型和基础框架搭建,算是把“骨架”给搭起来了。这次咱们进入更核心、也更“好玩”的部分:无线蓝牙遥控的实现。这不仅仅是让车动起来,而是要让它“听话”&#xff0c…

2026/7/28 3:57:19阅读更多 →
覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

🔹 工具基础介绍 OpenClaw 是开源生态中一款实用性较强的本地智能工具,凭借本地离线运行、可视化图形操作和任务自动化三大核心特性,赢得了众多用户的青睐。与普通在线对话AI工具不同,它属于能够直接操控本机软硬件的智能数字员工…

2026/7/27 1:14:34阅读更多 →
伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

所谓液压伺服阀体的精密激光焊接,是用激光束对阀座壳体(通常为不锈钢或铝合金)进行密封焊接,使阀体在21-35MPa的高压液压油或压缩气体中长期运行而不发生介质泄漏。液压伺服阀是高端液压系统的"大脑"。从航空航天飞行控…

2026/7/28 2:08:06阅读更多 →
D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南 【免费下载链接】d2dx D2DX is a complete solution to make Diablo II run well on modern PCs, with high fps and better resolutions. 项目地址: https://gitcode.com/gh_mirrors/d2/d2dx 你是否还在…

2026/7/28 1:38:28阅读更多 →
告别臃肿!3步让你的暗影精灵笔记本重获新生

告别臃肿!3步让你的暗影精灵笔记本重获新生

告别臃肿!3步让你的暗影精灵笔记本重获新生 【免费下载链接】OmenSuperHub Control Omen laptop performance, fan speeds, and keyboard lighting, and unlock power limits. 项目地址: https://gitcode.com/gh_mirrors/om/OmenSuperHub 你是否也曾为官方Om…

2026/7/28 0:00:29阅读更多 →
RAG必踩坑!财报法规检索不准?这款开源工具让答案浮出水面,准确率飙升98.7%!

RAG必踩坑!财报法规检索不准?这款开源工具让答案浮出水面,准确率飙升98.7%!

做 RAG 的人应该都踩过这个致命的坑:把几百页的财报、法规、技术手册扔给向量库,问一个具体问题,搜出来的全是沾边但没用的内容 —— 关键信息要么被硬切块拆碎了,要么藏在几十条结果的最下面。语义相似≠真正相关,这个…

2026/7/28 0:00:29阅读更多 →
抖音视频文案提取工具全指南:免费2026版、手机App、在线工具一网打尽

抖音视频文案提取工具全指南:免费2026版、手机App、在线工具一网打尽

2026年做短视频运营,从抖音上扒文案早就不是偷偷抄笔记的事了。我刚开始做内容的时候,每天刷半小时抖音,手动把爆款视频的口播敲进备忘录,一条2分钟的视频得花十来分钟,碰到语速快的还要反复回听。后来试了一圈工具&am…

2026/7/28 0:00:29阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/27 16:57:54阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/28 3:17:03阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/28 2:35:58阅读更多 →