自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Elasticsearch深度分頁全解:從原理到跳頁實戰(zhàn)

數(shù)據(jù)庫 其他數(shù)據(jù)庫
在數(shù)據(jù)爆炸的時代,分頁查詢已成為系統(tǒng)標配功能。但當面對億級數(shù)據(jù)量時,傳統(tǒng)的分頁方式卻可能成為壓垮系統(tǒng)的最后一根稻草。本文將深入剖析Elasticsearch深度分頁的成因,并提供常見的解決方案.

在數(shù)據(jù)爆炸的時代,分頁查詢已成為系統(tǒng)標配功能。但當面對億級數(shù)據(jù)量時,傳統(tǒng)的分頁方式卻可能成為壓垮系統(tǒng)的最后一根稻草。本文將深入剖析Elasticsearch深度分頁的成因,并提供常見的解決方案.

1.深度分頁:你以為的翻頁,其實是性能炸彈

分頁機制剖析

當使用from+size進行分頁時,Elasticsearch的處理流程暗藏隱患

# 典型分頁請求示例
GET /orders/_search
{
  "from": 1000,
  "size": 10,
  "sort": [{"create_time": "desc"}]
}

處理流程

  • 客戶端請求第N頁數(shù)據(jù)(from = 1000, size = 10)
  • 協(xié)調(diào)節(jié)點向所有分片廣播查詢請求
  • 每個分片在內(nèi)存中計算排序,準備前1010條結(jié)果
  • 合并所有分片返回的1010×分片數(shù)次數(shù)據(jù)
  • 最終截取第1000-1010條數(shù)據(jù)返回客戶端

性能災(zāi)難三宗罪

# 查看默認最大分頁限制
GET /_settings?include_defaults
# 輸出結(jié)果片段
"index.max_result_window" : "10000"

致命影響

  • 內(nèi)存黑洞:翻到第1000頁時,單個分片需處理1000×size數(shù)據(jù)量
  • 網(wǎng)絡(luò)風暴:分片數(shù)×數(shù)據(jù)量的跨節(jié)點傳輸消耗
  • 響應(yīng)懸崖:頁碼超過max_result_window(默認1w)時直接報錯

2.破局之道:Search After與Scroll API原理解析

Search After(游標分頁核心原理)

graph LR
    A[請求第一頁] --> B(返回排序值游標)
    B --> C[攜帶游標請求下一頁]
    C --> D{是否還有數(shù)據(jù)}
    D -- 是 --> C
    D -- 否 --> E[結(jié)束查詢]

技術(shù)本質(zhì)

  • 基于上一頁最后一條記錄的排序值進行分頁
  • 避免全局排序,僅保持單次查詢的順序一致性
  • 時間復(fù)雜度穩(wěn)定為O(size)

適用場景

  • 移動端瀑布流瀏覽
  • 后臺連續(xù)分頁查詢
  • 需要實時性的分頁需求

Spring Boot實現(xiàn)

// 構(gòu)建基礎(chǔ)查詢
SearchSourceBuilder builder = new SearchSourceBuilder()
    .size(10)
    .sort(SortBuilders.fieldSort("create_time").order(SortOrder.DESC))
    .sort(SortBuilders.fieldSort("_id")); // 保證排序唯一性
// 設(shè)置search_after參數(shù)
if (lastCreateTime != null && lastId != null) {
    builder.searchAfter(new Object[]{lastCreateTime, lastId});
}
SearchRequest request = new SearchRequest("orders")
    .source(builder);

Scroll API(滾動查詢)

核心原理

graph TB
    A[初始化Scroll] --> B(獲取scroll_id)
    B --> C[使用scroll_id分批獲取]
    C --> D{是否完成}
    D -- 否 --> C
    D -- 是 --> E[清除Scroll上下文]

技術(shù)本質(zhì)

  • 創(chuàng)建查詢的快照視圖
  • 通過保持搜索上下文實現(xiàn)批次獲取
  • 適合非實時的大數(shù)據(jù)量處理

適用場景

  • 全量數(shù)據(jù)導出
  • 離線數(shù)據(jù)分析
  • 大數(shù)據(jù)遷移場景

Spring Boot實現(xiàn)

// 初始化滾動查詢
SearchRequest request = new SearchRequest("orders");
request.scroll(TimeValue.timeValueMinutes(1L)); // 保持上下文1分鐘
// 后續(xù)獲取批次數(shù)據(jù)
SearchScrollRequest scrollRequest = new SearchScrollRequest(scrollId);
scrollRequest.scroll(TimeValue.timeValueSeconds(30L));

3.跳頁難題解決方案

跳頁問題本質(zhì)剖析

graph TD
    A[用戶請求第N頁] --> B{是否緩存過位置}
    B -- 是 --> C[直接使用緩存游標]
    B -- 否 --> D[估算近似位置]
    D --> E[二次校準查詢]
    E --> F[返回精確結(jié)果]

技術(shù)挑戰(zhàn)

  • 無法直接定位到任意偏移量
  • 傳統(tǒng)分頁方式性能不可接受
  • 需要平衡準確性與性能

混合分頁策略

public SearchResult queryProducts(int targetPage) {
    if (targetPage <= 100) {
        return traditionalPaging(targetPage); // 傳統(tǒng)分頁
    } else if (targetPage <= cachedMaxPage) {
        return searchAfterWithCache(targetPage); // 帶緩存的search_after
    } else {
        return timeRangeFilterPaging(targetPage); // 時間范圍過濾分頁
    }
}

跳頁緩存層設(shè)計

// Redis存儲分頁快照
public void cachePageSnapshot(int pageNum, Object[] searchAfterValues) {
    String key = "product_list:page:" + pageNum;
    redisTemplate.opsForValue().set(key, searchAfterValues, 5, TimeUnit.MINUTES);
}
// 獲取緩存游標
public Object[] getCachedSnapshot(int pageNum) {
    String key = "product_list:page:" + pageNum;
    return (Object[]) redisTemplate.opsForValue().get(key);
}

4.性能優(yōu)化全景方案

實測數(shù)據(jù)對比

分頁方式

10頁耗時

100頁耗時

1000頁耗時

內(nèi)存消耗

From/Size

120ms

450ms

超時失敗

Search_After

80ms

85ms

90ms

Scroll

100ms

110ms

120ms

測試環(huán)境:3節(jié)點集群,單個索引10個分片,500萬測試數(shù)據(jù)

5.最佳實踐指南

前端設(shè)計原則

  • 使用無限滾動替代傳統(tǒng)分頁
  • 提供精準過濾條件
  • 展示總條數(shù)范圍而非精確值

后端防御策略

// 分頁參數(shù)校驗
public void validatePageParams(int page, int size) {
    if (page > MAX_ALLOWED_PAGE) {
        throw new BusinessException("超出最大可查詢頁數(shù)");
    }
    if (size > 100) {
        throw new BusinessException("單頁數(shù)量不可超過100");
    }
}

監(jiān)控預(yù)警方案

# 監(jiān)控search_after上下文
GET _nodes/stats/indices/search?filter_path=**.open_contexts
# 檢查scroll上下文
GET _nodes/stats/indices/search?filter_path=**.scroll_current

當面對強制要求的精確跳頁場景時,可考慮預(yù)計算+二級緩存方案。通過定時任務(wù)預(yù)先建立熱點頁的游標映射表,結(jié)合短時緩存實現(xiàn)快速跳轉(zhuǎn)。您在實際項目中是如何解決這個難題的?

責任編輯:武曉燕 來源: JAVA充電
相關(guān)推薦

2020-04-28 22:12:30

Nginx正向代理反向代理

2022-02-28 10:05:12

組件化架構(gòu)設(shè)計從原組件化模塊化

2025-04-01 01:04:00

Redis集群緩存

2025-03-14 12:30:00

Redis RDBRedis數(shù)據(jù)庫

2021-05-11 07:51:30

React ref 前端

2021-10-04 09:14:18

ElasticSear深度分頁

2024-07-07 21:49:22

2009-11-11 10:21:25

路由選擇協(xié)議

2018-05-17 15:18:48

Logistic回歸算法機器學習

2025-04-02 07:29:14

2023-05-15 08:32:45

2018-03-30 18:17:10

MySQLLinux

2010-06-29 14:20:52

2024-03-27 10:14:48

2023-08-03 08:03:05

2023-02-07 08:55:04

進程棧內(nèi)存底層

2025-04-07 03:02:00

電腦內(nèi)存數(shù)據(jù)

2021-12-13 06:56:46

漏洞Log4j對象

2022-02-14 21:17:21

RPC框架協(xié)議

2017-07-06 11:34:17

神經(jīng)形態(tài)計算人工智能突觸
點贊
收藏

51CTO技術(shù)棧公眾號