【架构实战】ElasticSearch搜索集群:全文检索的艺术

作者:heimeiyingwang日期:2026/5/31

【架构实战】ElasticSearch搜索集群:å

¨æ–‡æ£€ç´¢çš„艺术

倒排索引、分片副本、搜索优化、实战案例

一、从一个真实的æ•

事说起

2024年双十一,某电商平台搜索系统在流量洪峰到来的那一刻,突然"哑火"了。

用户在搜索框输å
¥"iPhone 15 Pro Max",等了整整8秒,页面才刷出结果。而更诡异的是,有些用户搜索"手机壳",å±
然搜出了"手机支架"——相å
³æ€§å®Œå
¨é”™ä¹±ã€‚运维团队紧急排查,发现是ElasticSearché›†ç¾¤çš„æŸä¸ªåˆ†ç‰‡å› ä¸ºç£ç›˜IO瓶颈导致查询è¶
æ—¶ï¼Œè€Œå‰¯æœ¬åˆ†ç‰‡å› ä¸ºè´Ÿè½½å‡è¡¡ç­–ç•¥é—®é¢˜ï¼Œå
¨éƒ¨æ‰“在了同一台机器上。

"我们不是é
ç½®äº†å‰¯æœ¬å—ï¼Ÿä¸ºä»€ä¹ˆè¿˜ä¼šè¿™æ ·ï¼Ÿ"开发同学一脸懵。

"副本是é
ç½®äº†ï¼Œä½†ä½ 们把5个副本分片å
¨éƒ¨åˆ†é
åˆ°äº†åŒä¸€å°é«˜é
æœºå™¨ä¸Šï¼Œä»¥ä¸ºè¿™æ ·èƒ½æé«˜æ€§èƒ½ã€‚结果那台机器的磁盘IO被打满,查询å
¨éƒ¨è¶
时。"è¿ç»´åŒå­¦æ— å¥ˆåœ°è§£é‡Šã€‚

这个æ•
事告诉我们:ElasticSearchä¸æ˜¯å¼€ç®±å³ç”¨çš„æœç´¢å¼•æ“Žï¼Œç†è§£å ¶åº•å±‚åŽŸç†å¹¶æ­£ç¡®é ç½®ï¼Œæ‰èƒ½çœŸæ­£å‘æŒ¥å®ƒçš„å¨åŠ›ã€‚


äºŒã€æ ¸å¿ƒæ¦‚å¿µï¼šå€’æŽ’ç´¢å¼•â€”â€”æœç´¢çš„åŸºçŸ³

2.1 什么是倒排索引?

ä¼ ç»Ÿçš„å
³ç³»åž‹æ•°æ®åº“使用**正向索引**:文档ID → 文档å†
容。比如:

1文档ID: 1 → å†
2容: "iPhone 15 Pro Max 256GB 深空黑"
3文档ID: 2 → å†
4容: "iPhone 15 Pro 手机壳 透明"
5文档ID: 3 → å†
6容: "iPhone 14 Pro Max 手机壳 黑色"
7

如果要搜索"iPhone",数据库需要扫描所有文档,逐个匹é
â€”â€”è¿™å°±æ˜¯å ¨è¡¨æ‰«æï¼Œæ•ˆçŽ‡æžä½Žã€‚

而ElasticSearch使用**倒排索引**:词条 → 文档ID列表。

1词条          文档ID列表
2─────────────────────────
3iPhone       → [1, 2, 3]
415           → [1, 2]
5Pro          → [1, 2, 3]
6Max          → [1, 3]
7手机壳       → [2, 3]
8256GB        → [1]
9深空黑       → [1]
10透明         → [2]
11黑色         → [3]
12

现在搜索"iPhone",只需要在倒排索引中找到"iPhone"这个词条,直接得到文档ID列表[1, 2, 3]ï¼Œæ— éœ€æ‰«æä»»ä½•æ–‡æ¡£ã€‚è¿™å°±æ˜¯**O(1)级别**的查询效率。

2.2 倒排索引的结构

å€’æŽ’ç´¢å¼•ç”±ä¸‰ä¸ªæ ¸å¿ƒç»“æž„ç»„æˆï¼š

  1. Term Dictionary(词条字å
    **¸ï¼‰**:所有不重复的词条,按字å
    ¸åºæŽ’序。ElasticSearch使用FST(Finite State Transducer)压缩存储,å†
    å­˜å ç”¨æžå°ã€‚
  2. **Term Index(词条索引)**:Term Dictionary的索引,用于快速定位词条在磁盘上的位置。通常每128个词条建立一个索引项。
  3. **Posting List(倒排表)**:每个词条对应的文档ID列表。ElasticSearch使用Frame of Referenceç¼–ç å’ŒRoaring Bitmaps压缩,大å¹
    减少存储空间。
1Term Index (å†
2存) → Term Dictionary (磁盘) → Posting List (磁盘)
3     ↓                    ↓                      ↓
4   快速定位            词条详æƒ
5              文档ID列表
6

2.3 实战:查看倒排索引

我们可以通过ElasticSearch的_termvectorsAPI查看某个文档的倒排索引信息:

1GET /products/_termvectors/1?fields=name&term_statistics=true
2
3{
4  "term_vectors": {
5    "name": {
6      "terms": {
7        "iphone": {
8          "term_freq": 1,
9          "doc_freq": 3,
10          "ttf": 3
11        },
12        "15": {
13          "term_freq": 1,
14          "doc_freq": 2,
15          "ttf": 2
16        }
17      }
18    }
19  }
20}
21

å
¶ä¸­ï¼š

  • term_freq:该词条在当前文档中出现的次数
  • doc_freq:åŒ
    含该词条的文档数量(文档频率)
  • ttf:该词条在所有文档中出现的总次数

三、分片与副本:分布式的艺术

3.1 分片(Shard):数据的水平切分

ElasticSearch将一个索引的数据分散到多个分片中,每个分片是一个独立的Lucene索引。

为什么需要分片?

  1. **水平扩展**:单台机器存不下海量数据,分片让数据分散到多台机器
  2. **并行查询**:查询可以并行执行在多个分片上,提高性能

分片数量如何确定?

官方建议:**每个分片大小在10GB-50GB之间**,分片数量 = 数据总量 / 30GB。

1// 创建索引时指定分片数
2PUT /products
3{
4  "settings": {
5    "number_of_shards": 5,
6    "number_of_replicas": 1
7  }
8}
9

3.2 副本(Replica):高可用的保障

副本是分片的拷贝,用于:

  1. 容灾:主分片æ•
    障时,副本自动升级为主分片
  2. **负载均衡**:查询请求可以分发到副本上,提高查询吞吐量

副本数量如何确定?

  • 开发环境:0个副本(节省资源)
  • 生产环境:至少1个副本
  • 高可用场景:2个副本(å
    è®¸ä»»æ„2台机器同时æ•
    障)

3.3 分片分é

ç­–ç•¥

ElasticSearch通过分片分é **å™¨ï¼ˆShard Allocator)**å†³å®šåˆ†ç‰‡æ”¾åœ¨å“ªäº›èŠ‚ç‚¹ä¸Šã€‚æ ¸å¿ƒåŽŸåˆ™ï¼š

  1. **均衡原则**:尽量让每个节点的分片数量相近
  2. **感知原则**:避å
    ä¸»åˆ†ç‰‡å’Œå‰¯æœ¬åˆ†ç‰‡åˆ†é
    åˆ°åŒä¸€å°æœºå™¨
  3. **属性感知**ï¼šå¯ä»¥æ ¹æ®æœºæž¶ã€å¯ç”¨åŒºç­‰å±žæ€§åˆ†é
    ï¼Œé¿å
    å•点æ•
    障
1# elasticsearch.yml é
2ç½®æœºæž¶æ„ŸçŸ¥
3cluster.routing.allocation.awareness.attributes: rack_id
4
5node.attr.rack_id: rack1  # 节点1
6node.attr.rack_id: rack2  # 节点2
7

è¿™æ ·é
ç½®åŽï¼ŒElasticSearch会尽量将主分片和副本分片分é
åˆ°ä¸åŒçš„æœºæž¶ä¸Šã€‚

3.4 实战案例:分片分é

å¤±è´¥æŽ’查

**问题现象**:集群状态为Yellow,提示"分片分é
å¤±è´¥"。

**排查步骤**:

1// 1. 查看集群健康状态
2GET /_cluster/health
3
4{
5  "status": "yellow",
6  "unassigned_shards": 2
7}
8
9// 2. 查看分片分é
10è§£é‡Š
11GET /_cluster/allocation/explain
12
13{
14  "index": "products",
15  "shard": 1,
16  "primary": false,
17  "current_state": "unassigned",
18  "unassigned_info": {
19    "reason": "NODE_LEFT",
20    "at": "2024-11-11T10:00:00.000Z"
21  },
22  "can_allocate": "no",
23  "allocate_explanation": "cannot allocate because the node left the cluster"
24}
25

解决方案:

如果是节点临时æ•
障,等å¾
节点恢复即可。如果节点永ä¹
下线,需要调整分片分é
ç­–略:

1// 重新分é
2å‰¯æœ¬
3POST /_cluster/reroute?retry_failed=true
4

四、搜索优化:从å

¥é—¨åˆ°ç²¾é€š

4.1 查询DSL:构建复杂查询

ElasticSearch提供了强大的Query DSL(Domain Specific Language):

1// bool组合查询
2GET /products/_search
3{
4  "query": {
5    "bool": {
6      "must": [
7        { "match": { "name": "iPhone" }}
8      ],
9      "should": [
10        { "match": { "brand": "Apple" }},
11        { "range": { "price": { "lte": 10000 }}}
12      ],
13      "must_not": [
14        { "match": { "status": "下架" }}
15      ],
16      "filter": [
17        { "term": { "category": "手机" }}
18      ]
19    }
20  }
21}
22

å
¶ä¸­ï¼š

  • must:å¿
    须匹é
    ï¼Œå‚与评分
  • should:选择性匹é
    ï¼Œå‚与评分
  • must_not:å¿
    须不匹é
    ï¼Œä¸å‚与评分
  • filter:å¿
    须匹é
    ï¼Œä¸å‚与评分(性能更高)

4.2 相å

³æ€§è¯„分:BM25算法

ElasticSearch默认使用BM25算法计算文档相å
³æ€§è¯„分:

1score(D, Q) = Σ IDF(qi) * (f(qi, D) * (k1 + 1)) / (f(qi, D) + k1 * (1 - b + b * |D| / avgdl))
2

å
¶ä¸­ï¼š

  • f(qi, D):词条qi在文档D中的出现频率
  • |D|:文档D的长度
  • avgdl:所有文档的平均长度
  • k1、b:调节参数,默认k1=1.2,b=0.75

实战:调整BM25参数

1PUT /products
2{
3  "settings": {
4    "index": {
5      "similarity": {
6        "custom_bm25": {
7          "type": "BM25",
8          "k1": 1.5,
9          "b": 0.8
10        }
11      }
12    }
13  },
14  "mappings": {
15    "properties": {
16      "name": {
17        "type": "text",
18        "similarity": "custom_bm25"
19      }
20    }
21  }
22}
23

4.3 高亮显示:让结果更直观

1GET /products/_search
2{
3  "query": {
4    "match": { "name": "iPhone" }
5  },
6  "highlight": {
7    "fields": {
8      "name": {
9        "pre_tags": ["<em>"],
10        "post_tags": ["</em>"],
11        "fragment_size": 150,
12        "number_of_fragments": 3
13      }
14    }
15  }
16}
17
18// 返回结果
19{
20  "hits": {
21    "hits": [
22      {
23        "_source": {
24          "name": "iPhone 15 Pro Max 256GB 深空黑"
25        },
26        "highlight": {
27          "name": ["<em>iPhone</em> 15 Pro Max 256GB 深空黑"]
28        }
29      }
30    ]
31  }
32}
33

4.4 聚合分析:不只是搜索

ElasticSearch的聚合功能可以实现复杂的数据分析:

1// æŒ‰å“ç‰Œåˆ†ç»„ï¼Œè®¡ç®—å¹³å‡ä»·æ ¼å’Œé”€é‡
2GET /products/_search
3{
4  "size": 0,
5  "aggs": {
6    "brands": {
7      "terms": { "field": "brand.keyword", "size": 10 },
8      "aggs": {
9        "avg_price": { "avg": { "field": "price" }},
10        "total_sales": { "sum": { "field": "sales" }}
11      }
12    }
13  }
14}
15

五、实战案例:电商搜索系统架构

5.1 系统架构设计

1用户请求
2    ↓
3API网å
4³ï¼ˆé™æµã€é‰´æƒï¼‰
5    ↓
6搜索服务(查询重写、结果排序)
7    ↓
8ElasticSearch集群(3主3从)
9    ↓
10数据同步服务(MySQL → ES)
11

5.2 数据同步方案

方案一:双写模式

应用层同时写å
¥MySQLå’ŒElasticSearch:

1@Transactional
2public void saveProduct(Product product) {
3    // 1. 写å
4¥MySQL
5    productMapper.insert(product);
6    
7    // 2. 写å
8¥ElasticSearch
9    try {
10        elasticsearchTemplate.save(product);
11    } catch (Exception e) {
12        // 写å
13¥å¤±è´¥ï¼Œè®°å½•日志,异步补偿
14        log.error("ES写å
15¥å¤±è´¥", e);
16        mqService.send("es_sync_topic", product);
17    }
18}
19

优点:实现简单,实时性高
ç¼ºç‚¹ï¼šä»£ç ä¾µå
¥æ€§å¼ºï¼Œä¸€è‡´æ€§éš¾ä»¥ä¿è¯

方案二:CDC(Change Data Capture)

通过监听MySQL的binlog,实时同步到ElasticSearch:

1# Canalé
2ç½®
3canal.instance.master.address: 127.0.0.1:3306
4canal.instance.filter.regex: shop\\.products
5
6# 同步到ES
7canal.adapters:
8  - name: es
9    hosts: 127.0.0.1:9200
10    index: products
11    mapping:
12      id: _id
13      name: name
14      price: price
15

ä¼˜ç‚¹ï¼šä»£ç æ— ä¾µå
¥ï¼Œä¸€è‡´æ€§æœ‰ä¿éšœ
缺点:需要额外部署Canal,运维成本高

5.3 搜索性能优化

优化一:使用filter代替query

1// æ
2¢ï¼šä½¿ç”¨query
3GET /products/_search
4{
5  "query": {
6    "bool": {
7      "must": [
8        { "term": { "category": "手机" }},
9        { "term": { "brand": "Apple" }}
10      ]
11    }
12  }
13}
14
15// 快:使用filter
16GET /products/_search
17{
18  "query": {
19    "bool": {
20      "filter": [
21        { "term": { "category": "手机" }},
22        { "term": { "brand": "Apple" }}
23      ]
24    }
25  }
26}
27

filter不计算评分,且会被缓存,性能更高。

优化二:预热缓存

在业务低峰期预热查询缓存:

1@Scheduled(cron = "0 0 3 * * ?")
2public void warmUpCache() {
3    List<String> hotKeywords = getHotKeywords();
4    for (String keyword : hotKeywords) {
5        elasticsearchTemplate.query(keyword);
6    }
7}
8

优化三:异步查询

å¯¹äºŽéžæ ¸å¿ƒæŸ¥è¯¢ï¼ˆå¦‚æŽ¨èã€å¹¿å‘Šï¼‰ï¼Œä½¿ç”¨å¼‚æ­¥æŸ¥è¯¢ï¼š

1CompletableFuture<List<Product>> recommendFuture = CompletableFuture.supplyAsync(() -> {
2    return recommendService.query(userId);
3});
4
5CompletableFuture<List<Ad>> adFuture = CompletableFuture.supplyAsync(() -> {
6    return adService.query(userId);
7});
8
9// ç­‰å¾
10所有查询完成
11CompletableFuture.allOf(recommendFuture, adFuture).join();
12

å

­ã€è¸©å‘实录

踩坑一:深度分页性能问题

**问题**:查询第10000页,每页10条,耗时10秒。

1GET /products/_search
2{
3  "from": 100000,
4  "size": 10,
5  "query": { "match_all": {} }
6}
7

**åŽŸå› **:ElasticSearch需要查询所有分片的from+size条数据,在协调节点排序后取[from, from+size]。from越大,排序的数据越多,性能越差。

解决方案:使用search_after代替from/size:

1// 第一次查询
2GET /products/_search
3{
4  "size": 10,
5  "sort": [
6    { "_id": "asc" }
7  ]
8}
9
10// 后续查询
11GET /products/_search
12{
13  "size": 10,
14  "sort": [
15    { "_id": "asc" }
16  ],
17  "search_after": ["AVd3d3d3d3d3d3d3"]
18}
19

è¸©å‘äºŒï¼šå­—æ®µç±»åž‹é”™è¯¯å¯¼è‡´æ— æ³•èšåˆ

**问题**:对price字段聚合时报错。

1GET /products/_search
2{
3  "aggs": {
4    "price_stats": { "stats": { "field": "price" }}
5  }
6}
7
8// 报错
9{
10  "error": {
11    "type": "illegal_argument_exception",
12    "reason": "Field [price] of type [text] is not supported for aggregation"
13  }
14}
15

**åŽŸå› **:priceå­—æ®µè¢«æ˜ å°„ä¸ºtext类型,text类型不支持聚合。

解决方案:使用keywordç±»åž‹æˆ–æ·»åŠ å­å­—æ®µï¼š

1PUT /products/_mapping
2{
3  "properties": {
4    "price": {
5      "type": "text",
6      "fields": {
7        "keyword": { "type": "keyword" },
8        "double": { "type": "double" }
9      }
10    }
11  }
12}
13
14// 使用子字段聚合
15GET /products/_search
16{
17  "aggs": {
18    "price_stats": { "stats": { "field": "price.double" }}
19  }
20}
21

踩坑三:集群脑裂问题

**问题**:集群出现两个Master节点,数据不一致。

**åŽŸå› **ï¼šç½‘ç»œåˆ†åŒºå¯¼è‡´éƒ¨åˆ†èŠ‚ç‚¹æ— æ³•é€šä¿¡ï¼Œå„è‡ªé€‰ä¸¾å‡ºMaster。

解决方案:

1# elasticsearch.yml
2# 设置最小主节点数 = 节点数/2 + 1
3discovery.zen.minimum_master_nodes: 2
4
5# 或è€
6使用7.x+版本的自动é
7ç½®
8cluster.initial_master_nodes: ["node1", "node2", "node3"]
9

踩坑四:JVMå †å†

存设置不当

**问题**:频繁Full GC,查询è¶
时。

**åŽŸå› **ï¼šå †å†
存设置过大,è¶
过物理å†
存的50%,导致大量å†
存用于Page Cache,反而降低性能。

解决方案:

1# jvm.options
2-Xms16g
3-Xmx16g
4
5# å †å†
6存不è¶
7过物理å†
8存的50%,且不è¶
9过32GB
10# Lucene利用操作系统的Page CacheåŠ é€ŸæŸ¥è¯¢ï¼Œå †å†
11存过大反而影响性能
12

七、总结

ElasticSearch作为分布式搜索引擎,å
¶æ ¸å¿ƒä¼˜åŠ¿åœ¨äºŽï¼š

  1. **倒排索引**:O(1)级别的查询效率
  2. **分片副本**:水平扩展和高可用保障
  3. 丰富的查询DSL:支持复杂查询和聚合分析
  4. **分布式架构**:自动分片分é
    å’Œæ•
    障恢复

但同时,ElasticSearch也有å
¶å¤æ‚性:

  1. **分片规划**:分片数量和大小需要合理规划
  2. **数据一致性**:与MySQLç­‰å
    ³ç³»åž‹æ•°æ®åº“的同步方案需要谨æ
    Žé€‰æ‹©
  3. **性能优化**:深度分页、字段类型、JVMé
    ç½®ç­‰éƒ½éœ€è¦æ·±å
    ¥ç†è§£
  4. **运维复杂度**:集群监控、æ•
    障排查、容量规划都需要专业能力

å

«ã€æ€è€ƒé¢˜

  1. å¦‚æžœä½ çš„ä¸šåŠ¡éœ€è¦æ”¯æŒ"搜索推荐"(用户输å
    ¥æ—¶å®žæ—¶æŽ¨èæœç´¢è¯ï¼‰ï¼Œä½ 会如何设计?需要考虑哪些技术点?
  2. ElasticSearchå’ŒMySQL各有优劣,什么场景下应该选择ElasticSearch作为主存储?什么场景下应该保持MySQL为主存储,ElasticSearchä»
    ä½œä¸ºæœç´¢åŠ é€Ÿï¼Ÿ
  3. 在微服务架构下,如何保证ElasticSearchæ•°æ®ä¸Žå„ä¸ªå¾®æœåŠ¡æ•°æ®çš„ä¸€è‡´æ€§ï¼Ÿä½ ä¼šé€‰æ‹©å“ªç§åŒæ­¥æ–¹æ¡ˆï¼Ÿ

九、个人观点

在我参与过的多个项目中,ElasticSearch最常见的误区是:**把它当作数据库来用**。

很多团队直接把业务数据存到ElasticSearch,不再使用MySQL。这在初期确实简单高效,但随着业务发展,问题逐渐暴露:

  1. **事务支持弱**:ElasticSearch没有完整的事务机制,复杂业务逻辑难以实现
  2. **更新性能差**:频繁更新会导致大量segment文件,查询性能下降
  3. 数据一致性难保证:分布式环境下的数据一致性是个大问题

我的建议是:ElasticSearch作为搜索引擎,MySQLä½œä¸ºæ•°æ®å­˜å‚¨ï¼Œä¸¤è€ å„å¸å ¶èŒã€‚é€šè¿‡CDC或双写模式保持数据同步,既享受ElasticSearch的搜索能力,又保留MySQL的事务特性。

另一个常见误区是:**忽视集群运维**。很多团队搭建完集群就不管了,直到出问题才临时抱佛脚。建议从项目初期就建立完善的监控体系(使用ElasticSearch Head、Kibana、Prometheus等),定期进行容量规划和æ•
障演练。

最后,ElasticSearchçš„å­¦ä¹ æ›²çº¿ç¡®å®žé™¡å³­ï¼Œä½†ä¸€æ—¦æŽŒæ¡ï¼Œä½ ä¼šå‘çŽ°å®ƒæ˜¯ä¸€ä¸ªå¼ºå¤§è€Œä¼˜é›
çš„æœç´¢å¼•æ“Žã€‚å¸Œæœ›è¿™ç¯‡æ–‡ç« èƒ½å¸®åŠ©ä½ å°‘èµ°å¼¯è·¯ï¼Œåœ¨å®žè·µä¸­çœŸæ­£å‘æŒ¥ElasticSearch的威力。


ä½œè€ ï¼šæž¶æž„å®žæˆ˜ç³»åˆ— | 字数:约4500å­—


【架构实战】ElasticSearch搜索集群:全文检索的艺术》 是转载文章,点击查看原文


相关推荐


豆包收费了:3.45亿用户,一个“豆包型人格“的道歉经济学
倔强的石头_2026/5/9

5月4号,两个微博热搜几乎同时炸了——#豆包错误率# 和 #豆包笨还收费#。 前一天,豆包刚刚在App Store页面更新了付费订阅声明:标准版68元/月,加强版200元/月,专业版500元/月。作为目前国内月活超过3.45亿的AI助手——这个数字意味着大约每四个中国人里就有一个人在用豆包——这是字节跳动第一次正式给豆包贴上价格标签。 但市场的反应不是期待,而是愤怒。 “又笨又收费,说平时用免费版,经常答非所问,信息出错,逻辑也不严谨,有时候还一本正经地胡说八道,基础功能都没做好。” “免费的


解锁AI编程密码:程序员常用的10个AI提示词
小码哥_常2026/4/30

解锁AI编程密码:程序员常用的10个AI提示词 引言:AI 时代的编程利器 在当今数字化浪潮中,编程领域正经历着前所未有的变革,AI 的加入让程序员们如虎添翼。有这样一个真实的故事,程序员小李在开发一个电商项目的订单管理模块时,遇到了性能瓶颈。原本处理大量订单数据时需要耗费很长时间,导致用户在下单和查询订单状态时响应迟缓。小李尝试了各种常规优化手段,但效果甚微,他陷入了困境,项目进度也因此受阻。 后来,小李了解到可以借助 AI 来解决问题。他在 AI 编程助手的输入框中输入了这样一个提示词:“A


GPT-Image-2 真有点夯:中文不乱码了!GPT-Image-2的入口在哪?教你如何确认自己是否被灰度推送了 GPT-Image-2
摆烂工程师2026/4/21

不知道大家有没有被 OpenAI 最近推出的 GPT-Image-2 惊讶到! 这几天,我用 GPT-Image-2 制作了各种主题的图片,简直夯爆了! 首先汉字提升巨大!另外就是高密度的文字生成,几乎没有乱码! 测试出来的效果,大家直接去生成对比,目前 GPT-Image-2 就是文生图的新王。 比 Nano Banana Pro 香多了! 怎么体验 GPT-Image-2 呢? 目前,官方已经进行灰度分发到 ChatGPT 上,优先美区,只要订阅了 Plus、Pro、Business 等用户


越用越强不是广告语:拆解 Hermes Agent 的三层学习机制
小墨同学boy2026/4/12

用 AI agent 有一段时间了,有个问题一直没解决:每次开新会话,它对我的项目和习惯还是一无所知。上下文配置文件里写了不少,但写进去的是静态的——它不会自己学,也不会根据我真实的操作习惯去调整。跑得熟不熟,完全取决于我自己有没有空去维护那份文件。 Hermes Agent 是 Nous Research 今年二月发布的开源代理框架(MIT 协议),主打的就是解决这个问题——让 agent 从使用中自己学,不靠你手动补。这篇主要拆它三层学习机制怎么运转,以及和 OpenClaw 的根本差在哪里


记录 idea 启动 tomcat 控制台输出乱码问题解决
2601_949818092026/4/4

文章目录 问题现象解决排查过程 1. **检查 idea 编码设置**2. **检查 tomcat 配置**3.检查 idea 配置文件4.在 Help 菜单栏中,修改`Custom VM Options`完成后保存,并重启 idea 问题现象 运行 tomcat 后,控制台输出乱码 解决排查过程 1. 检查 idea 编码设置 进入 File -> Settings在设置窗口中,导航到 Editor -> File Encodings。确保 Gl


【iOS】Effective Objective-C第四章
库奇噜啦呼2026/3/27

【iOS】Effective Objective-C第四章 协议与分类通过委托与数据源协议进行对象间通信将类的实现代码分散到便于管理的数个分类之中勿在分类中声明属性使用“class-continuation分类“隐藏实现细节通过协议提供匿名对象 协议与分类 协议和分类都是OC的一项重要语言特性。 协议:OC不支持多重继承,因而我们把某个类该实现的一系列方法定义在协议里面。协议最为常见的用途是实现委托模式。分类:利用分类,我们无须继承子类即可直接为当前类添加方法。 通过委托与数据源协


【Linux】 Ubuntu 与 CentOS 新手安装指南,避坑要点全总结
我不是呆头2026/3/19

【Linux】Ubuntu 与 CentOS 新手安装指南,避坑要点全总结 摘要 (Abstract) 踏入 Linux 世界的第一步,往往是令人望而生畏的“安装”。在众多发行版中,Ubuntu 和 CentOS 无疑是两个最常被提及的名字:一个(Ubuntu)是桌面和开发者的宠儿,另一个(CentOS)则是企业级服务器的标杆。然而,对于新手而言,从选择版本、制作启动盘到最关键的磁盘分区,每一步都暗藏“坑点”。本文是一篇面向零基础新手的“避坑”指南,旨在通过详细对比 Ubuntu 和


人工智能、机器学习和深度学习,其实不是一回事
IvanCodes2026/3/10

一、人工智能、机器学习与深度学习的真正区别 在当今科技领域,我们经常听到人工智能、机器学习和深度学习这三个词。它们虽然相关,但含义不同。 1.1 人工智能 人工智能是计算机科学的一个分支,旨在研究如何合成与分析能够像人一样行动的计算主体。简单来说,AI 的目标是利用计算机来模拟甚至替代人类大脑的功能。 一个理想的 AI 系统通常具备以下特征:像人一样思考、 像人一样行动、理性地思考与行动。 1.2 机器学习 机器学习是实现人工智能的一种途径。它的核心定义是:赋予计算机在没有被显式


零基础搭建WordPress网站完整流程
柠檬味的Cat2026/3/2

WordPress(简称WP)作为全球占比超43%的开源内容管理系统(CMS),凭借免费易用、插件生态丰富、可扩展性强的优势,成为个人博客、企业官网、技术文档站的首选建站工具。本文针对CSDN新手用户,梳理从前期准备到网站上线、后期优化的全流程,每一步都附具体操作和避坑提示,无需专业开发基础,跟着做就能快速搭建属于自己的WP网站。 核心流程概览:准备工作(域名+服务器)→ 服务器环境配置 → WordPress程序安装 → 网站基础设置 → 主题与插件配置 → 安全加固与性能优化 → 网站上线


构建工具的第三次革命:从 Rollup 到 Rust Bundler,我是如何设计 robuild 的
sunny_2026/2/22

本文将从第一人称实战视角,深入探讨前端构建工具的技术演进,以及我在设计 robuild 过程中的架构思考与工程实践。 引言:为什么我们需要又一个构建工具? 在开始正文之前,我想先回答一个无法回避的问题:在 Webpack、Rollup、esbuild、Vite 已经如此成熟的今天,为什么还要设计一个新的构建工具? 答案很简单:库构建与应用构建是两个本质不同的问题域。 Webpack 为复杂应用而生,Vite 为开发体验而生,esbuild 为速度而生。但当我们需要构建一个 npm 库时,我们需

首页编辑器站点地图

本站内容在 CC BY-SA 4.0 协议下发布

Copyright © 2026 聚合阅读