主頁 > 資料庫 > ElasticSearch深度分頁詳解

ElasticSearch深度分頁詳解

2022-11-16 07:29:21 資料庫

1 前言

ElasticSearch是一個實時的分布式搜索與分析引擎,常用于大量非結構化資料的存盤和快速檢索場景,具有很強的擴展性,縱使其有諸多優點,在搜索領域遠超關系型資料庫,但依然存在與關系型資料庫同樣的深度分頁問題,本文就此問題做一個實踐性分析探討

2 from + size分頁方式

from + size分頁方式是ES最基本的分頁方式,類似于關系型資料庫中的limit方式,from引數表示:分頁起始位置;size引數表示:每頁獲取資料條數,例如:

GET /wms_order_sku/_search
{
  "query": {
    "match_all": {}
  },
  "from": 10,
  "size": 20
}

 

該條DSL陳述句表示從搜索結果中第10條資料位置開始,取之后的20條資料作為結果回傳,這種分頁方式在ES集群內部是如何執行的呢?

在ES中,搜索一般包括2個階段,Query階段和Fetch階段,Query階段主要確定要獲取哪些doc,也就是回傳所要獲取doc的id集合,Fetch階段主要通過id獲取具體的doc,

2.1 Query階段

 

如上圖所示,Query階段大致分為3步:

  • 第一步:Client發送查詢請求到Server端,Node1接收到請求然后創建一個大小為from + size的優先級佇列用來存放結果,此時Node1被稱為coordinating node(協調節點);
  • 第二步:Node1將請求廣播到涉及的shard上,每個shard內部執行搜索請求,然后將執行結果存到自己內部的大小同樣為from+size的優先級佇列里;
  • 第三步:每個shard將暫存的自身優先級佇列里的結果返給Node1,Node1拿到所有shard回傳的結果后,對結果進行一次合并,產生一個全域的優先級佇列,存在Node1的優先級佇列中,(如上圖中,Node1會拿到(from + size) * 6 條資料,這些資料只包含doc的唯一標識_id和用于排序的_score,然后Node1會對這些資料合并排序,選擇前from + size條資料存到優先級佇列);

2.2 Fetch階段

 

如上圖所示,當Query階段結束后立馬進入Fetch階段,Fetch階段也分為3步:

  • 第一步:Node1根據剛才合并后保存在優先級佇列中的from+size條資料的id集合,發送請求到對應的shard上查詢doc資料詳情;
  • 第二步:各shard接收到查詢請求后,查詢到對應的資料詳情并回傳為Node1;(Node1中的優先級佇列中保存了from + size條資料的_id,但是在Fetch階段并不需要取回所有資料,只需要取回從from到from + size之間的size條資料詳情即可,這size條資料可能在同一個shard也可能在不同的shard,因此Node1使用multi-get來提高性能)
  • 第三步:Node1獲取到對應的分頁資料后,回傳給Client;

2.3 ES示例

依據上述我們對from + size分頁方式兩階段的分析會發現,假如起始位置from或者頁條數size特別大時,對于資料查詢和coordinating node結果合并都是巨大的性能損耗,

例如:索引 wms_order_sku 有1億資料,分10個shard存盤,當一個請求的from = 1000000, size = 10,在Query階段,每個shard就需要回傳1000010條資料的_id和_score資訊,而coordinating node就需要接收10 * 1000010條資料,拿到這些資料后需要進行全域排序取到前1000010條資料的_id集合保存到coordinating node的優先級佇列中,后續在Fetch階段再去獲取那10條資料的詳情回傳給客戶端,

分析:這個例子的執行程序中,在Query階段會在每個shard上均有巨大的查詢量,回傳給coordinating node時需要執行大量資料的排序操作,并且保存到優先級佇列的資料量也很大,占用大量節點機器記憶體資源,

2.4 實作示例

 

private SearchHits getSearchHits(BoolQueryBuilder queryParam, int from, int size, String orderField) {
        SearchRequestBuilder searchRequestBuilder = this.prepareSearch();
        searchRequestBuilder.setQuery(queryParam).setFrom(from).setSize(size).setExplain(false);
        if (StringUtils.isNotBlank(orderField)) {
            searchRequestBuilder.addSort(orderField, SortOrder.DESC);
        }
        log.info("getSearchHits searchBuilder:{}", searchRequestBuilder.toString());
        SearchResponse searchResponse = searchRequestBuilder.execute().actionGet();
        log.info("getSearchHits searchResponse:{}", searchResponse.toString());
        return searchResponse.getHits();
    }

 

2.5 小結

其實ES對結果視窗的回傳資料有默認10000條的限制(引數:index.max_result_window = 10000),當from + size的條數大于10000條時ES提示可以通過scroll方式進行分頁,非常不建議調大結果視窗引數值,

 

3 Scroll分頁方式

scroll分頁方式類似關系型資料庫中的cursor(游標),首次查詢時會生成并快取快照,回傳給客戶端快照讀取的位置引數(scroll_id),后續每次請求都會通過scroll_id訪問快照實作快速查詢需要的資料,有效降低查詢和存盤的性能損耗,

3.1 執行程序

scroll分頁方式在Query階段同樣也是coordinating node廣播查詢請求,獲取、合并、排序其他shard回傳的資料_id集合,不同的是scroll分頁方式會將回傳資料_id的集合生成快照保存到coordinating node上,Fetch階段以游標的方式從生成的快照中獲取size條資料的_id,并去其他shard獲取資料詳情回傳給客戶端,同時將下一次游標開始的位置標識_scroll_id也回傳,這樣下次客戶端發送獲取下一頁請求時帶上scroll_id標識,coordinating node會從scroll_id標記的位置獲取接下來size條資料,同時再次回傳新的游標位置標識scroll_id,這樣依次類推直到取完所有資料,

3.2 ES示例

第一次查詢時不需要傳入_scroll_id,只要帶上scroll的過期時間引數(scroll=1m)、每頁大小(size)以及需要查詢資料的自定義條件即可,查詢后不僅會回傳結果資料,還會回傳_scroll_id,

GET /wms_order_sku2021_10/_search?scroll=1m
{
  "query": {
    "bool": {
      "must": [
        {
          "range": {
            "shipmentOrderCreateTime": {
              "gte": "2021-10-04 00:00:00",
              "lt": "2021-10-15 00:00:00"
            }
          }
        }
      ]
    }
  },
  "size": 20
}

 

 

第二次查詢時不需要指定索引,在JSON請求體中帶上前一個查詢回傳的scroll_id,同時傳入scroll引數,指定重繪搜索結果的快取時間(上一次查詢快取1分鐘,本次查詢會再次重置快取時間為1分鐘)

GET /_search/scroll
{
  "scroll":"1m",
  "scroll_id" : "DnF1ZXJ5VGhlbkZldGNoIAAAAAJFQdUKFllGc2E4Y2tEUjR5VkpKbkNtdDFMNFEAAAACJj74YxZmSWhNM2tVbFRiaU9VcVpDUWpKSGlnAAAAAiY--F4WZkloTTNrVWxUYmlPVXFaQ1FqSkhpZwAAAAJMQKhIFmw2c1hwVFk1UXppbDhZcW1za2ZzdlEAAAACRUHVCxZZRnNhOGNrRFI0eVZKSm5DbXQxTDRRAAAAAkxAqEcWbDZzWHBUWTVRemlsOFlxbXNrZnN2UQAAAAImPvhdFmZJaE0za1VsVGJpT1VxWkNRakpIaWcAAAACJ-MhBhZOMmYzWVVMbFIzNkdnN1FwVXVHaEd3AAAAAifjIQgWTjJmM1lVTGxSMzZHZzdRcFV1R2hHdwAAAAIn4yEHFk4yZjNZVUxsUjM2R2c3UXBVdUdoR3cAAAACJ5db8xZxeW5NRXpHOFR0eVNBOHlOcXBGbWdRAAAAAifjIQkWTjJmM1lVTGxSMzZHZzdRcFV1R2hHdwAAAAJFQdUMFllGc2E4Y2tEUjR5VkpKbkNtdDFMNFEAAAACJj74YhZmSWhNM2tVbFRiaU9VcVpDUWpKSGlnAAAAAieXW_YWcXluTUV6RzhUdHlTQTh5TnFwRm1nUQAAAAInl1v0FnF5bk1Fekc4VHR5U0E4eU5xcEZtZ1EAAAACJ5db9RZxeW5NRXpHOFR0eVNBOHlOcXBGbWdRAAAAAkVB1Q0WWUZzYThja0RSNHlWSkpuQ210MUw0UQAAAAImPvhfFmZJaE0za1VsVGJpT1VxWkNRakpIaWcAAAACJ-MhChZOMmYzWVVMbFIzNkdnN1FwVXVHaEd3AAAAAkVB1REWWUZzYThja0RSNHlWSkpuQ210MUw0UQAAAAImPvhgFmZJaE0za1VsVGJpT1VxWkNRakpIaWcAAAACTECoShZsNnNYcFRZNVF6aWw4WXFtc2tmc3ZRAAAAAiY--GEWZkloTTNrVWxUYmlPVXFaQ1FqSkhpZwAAAAJFQdUOFllGc2E4Y2tEUjR5VkpKbkNtdDFMNFEAAAACRUHVEBZZRnNhOGNrRFI0eVZKSm5DbXQxTDRRAAAAAiY--GQWZkloTTNrVWxUYmlPVXFaQ1FqSkhpZwAAAAJFQdUPFllGc2E4Y2tEUjR5VkpKbkNtdDFMNFEAAAACJj74ZRZmSWhNM2tVbFRiaU9VcVpDUWpKSGlnAAAAAkxAqEkWbDZzWHBUWTVRemlsOFlxbXNrZnN2UQAAAAInl1v3FnF5bk1Fekc4VHR5U0E4eU5xcEZtZ1EAAAACTECoRhZsNnNYcFRZNVF6aWw4WXFtc2tmc3ZR"
}
 

 

 

3.3 實作示例

 

protected <T> Page<T> searchPageByConditionWithScrollId(BoolQueryBuilder queryParam, Class<T> targetClass, Page<T> page) throws IllegalAccessException, InstantiationException, InvocationTargetException {
        SearchResponse scrollResp = null;
        String scrollId = ContextParameterHolder.get("scrollId");
        if (scrollId != null) {
            scrollResp = getTransportClient().prepareSearchScroll(scrollId).setScroll(new TimeValue(60000)).execute()
                    .actionGet();
        } else {
            logger.info("基于scroll的分頁查詢,scrollId為空");
            scrollResp = this.prepareSearch()
                    .setSearchType(SearchType.QUERY_AND_FETCH)
                    .setScroll(new TimeValue(60000))
                    .setQuery(queryParam)
                    .setSize(page.getPageSize()).execute().actionGet();
            ContextParameterHolder.set("scrollId", scrollResp.getScrollId());
        }
        SearchHit[] hits = scrollResp.getHits().getHits();
        List<T> list = new ArrayList<T>(hits.length);
        for (SearchHit hit : hits) {
            T instance = targetClass.newInstance();
            this.convertToBean(instance, hit);
            list.add(instance);
        }
        page.setTotalRow((int) scrollResp.getHits().getTotalHits());
        page.setResult(list);
        return page;
    }

3.4 小結

scroll分頁方式的優點就是減少了查詢和排序的次數,避免性能損耗,缺點就是只能實作上一頁、下一頁的翻頁功能,不兼容通過頁碼查詢資料的跳頁,同時由于其在搜索初始化階段會生成快照,后續資料的變化無法及時體現在查詢結果,因此更加適合一次性批量查詢或非實時資料的分頁查詢,

啟用游標查詢時,需要注意設定期望的過期時間(scroll = 1m),以降低維持游標查詢視窗所需消耗的資源,注意這個過期時間每次查詢都會重置重繪為1分鐘,表示游標的閑置失效時間(第二次以后的查詢必須帶scroll = 1m引數才能實作)

4 Search After分頁方式

Search After分頁方式是ES 5新增的一種分頁查詢方式,其實作的思路同Scroll分頁方式基本一致,通過記錄上一次分頁的位置標識,來進行下一次分頁資料的查詢,相比于Scroll分頁方式,它的優點是可以實時體現資料的變化,解決了查詢快照導致的查詢結果延遲問題,

4.1 執行程序

Search After方式也不支持跳頁功能,每次查詢一頁資料,第一次每個shard回傳一頁資料(size條),coordinating node一共獲取到 shard數 * size條資料 , 接下來coordinating node在記憶體中進行排序,取出前size條資料作為第一頁搜索結果回傳,當拉取第二頁時,不同于Scroll分頁方式,Search After方式會找到第一頁資料被拉取的最大值,作為第二頁資料拉取的查詢條件,

這樣每個shard還是回傳一頁資料(size條),coordinating node獲取到 shard數 * size條資料進行記憶體排序,取得前size條資料作為全域的第二頁搜索結果,
后續分頁查詢以此類推…

4.2 ES示例

第一次查詢只傳入排序欄位和每頁大小size

GET /wms_order_sku2021_10/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "range": {
            "shipmentOrderCreateTime": {
              "gte": "2021-10-12 00:00:00",
              "lt": "2021-10-15 00:00:00"
            }
          }
        }
      ]
    }
  },
  "size": 20,
  "sort": [
    {
      "_id": {
        "order": "desc"
      }
    },{
      "shipmentOrderCreateTime":{
        "order": "desc"
      }
    }
  ]
}

 

 

 

接下來每次查詢時都帶上本次查詢的最后一條資料的 _id 和 shipmentOrderCreateTime欄位,回圈往復就能夠實作不斷下一頁的功能

GET /wms_order_sku2021_10/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "range": {
            "shipmentOrderCreateTime": {
              "gte": "2021-10-12 00:00:00",
              "lt": "2021-10-15 00:00:00"
            }
          }
        }
      ]
    }
  },
  "size": 20,
  "sort": [
    {
      "_id": {
        "order": "desc"
      }
    },{
      "shipmentOrderCreateTime":{
        "order": "desc"
      }
    }
  ],
  "search_after": ["SO-460_152-1447931043809128448-100017918838",1634077436000]
}

 

 

4.3 實作示例

 

 

public <T> ScrollDto<T> queryScrollDtoByParamWithSearchAfter(
            BoolQueryBuilder queryParam, Class<T> targetClass, int pageSize, String afterId,
            List<FieldSortBuilder> fieldSortBuilders) {
        SearchResponse scrollResp;
        long now = System.currentTimeMillis();
        SearchRequestBuilder builder = this.prepareSearch();
        if (CollectionUtils.isNotEmpty(fieldSortBuilders)) {
            fieldSortBuilders.forEach(builder::addSort);
        }
        builder.addSort("_id", SortOrder.DESC);
        if (StringUtils.isBlank(afterId)) {
            log.info("queryScrollDtoByParamWithSearchAfter基于afterId的分頁查詢,afterId為空");
            SearchRequestBuilder searchRequestBuilder = builder.setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
                    .setQuery(queryParam).setSize(pageSize);
            scrollResp = searchRequestBuilder.execute()
                    .actionGet();
            log.info("queryScrollDtoByParamWithSearchAfter基于afterId的分頁查詢,afterId 為空,searchRequestBuilder:{}", searchRequestBuilder);
        } else {
            log.info("queryScrollDtoByParamWithSearchAfter基于afterId的分頁查詢,afterId=" + afterId);
            Object[] afterIds = JSON.parseObject(afterId, Object[].class);
            SearchRequestBuilder searchRequestBuilder = builder.setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
                    .setQuery(queryParam).searchAfter(afterIds).setSize(pageSize);
            log.info("queryScrollDtoByParamWithSearchAfter基于afterId的分頁查詢,searchRequestBuilder:{}", searchRequestBuilder);
            scrollResp = searchRequestBuilder.execute()
                    .actionGet();
        }
        SearchHit[] hits = scrollResp.getHits().getHits();
        log.info("queryScrollDtoByParamWithSearchAfter基于afterId的分頁查詢,totalRow={}, size={}, use time:{}", scrollResp.getHits().getTotalHits(), hits.length, System.currentTimeMillis() - now);
        now = System.currentTimeMillis();

        List<T> list = new ArrayList<>();
        if (ArrayUtils.getLength(hits) > 0) {
            list = Arrays.stream(hits)
                    .filter(Objects::nonNull)
                    .map(SearchHit::getSourceAsMap)
                    .filter(Objects::nonNull)
                    .map(JSON::toJSONString)
                    .map(e -> JSON.parseObject(e, targetClass))
                    .collect(Collectors.toList());
            afterId = JSON.toJSONString(hits[hits.length - 1].getSortValues());
        }
        log.info("es資料轉換bean,totalRow={}, size={}, use time:{}", scrollResp.getHits().getTotalHits(), hits.length, System.currentTimeMillis() - now);
        return ScrollDto.<T>builder().scrollId(afterId).result(list).totalRow((int) scrollResp.getHits().getTotalHits()).build();
    }

4.4 小結

Search After分頁方式采用記錄作為游標,因此Search After要求doc中至少有一條全域唯一變數(示例中使用_id和時間戳,實際上_id已經是全域唯一),Search After方式是無狀態的分頁查詢,因此資料的變更能夠及時的反映在查詢結果中,避免了Scroll分頁方式無法獲取最新資料變更的缺點,同時Search After不用維護scroll_id和快照,因此也節約大量資源,

5 總結思考

5.1 ES三種分頁方式對比總結

 

  • 如果資料量小(from+size在10000條內),或者只關注結果集的TopN資料,可以使用from/size 分頁,簡單粗暴
  • 資料量大,深度翻頁,后臺批處理任務(資料遷移)之類的任務,使用 scroll 方式
  • 資料量大,深度翻頁,用戶實時、高并發查詢需求,使用 search after 方式

5.2 個人思考

  • 在一般業務查詢頁面中,大多情況都是10-20條資料為一頁,10000條資料也就是500-1000頁,正常情況下,對于用戶來說,有極少需求翻到比較靠后的頁碼來查看資料,更多的是通過查詢條件框定一部分資料查看其詳情,因此在業務需求敲定初期,可以同業務人員商定1w條資料的限定,超過1w條的情況可以借助匯出資料到Excel表,在Excel表中做具體的操作,
  • 如果給匯出中心回傳大量資料的場景可以使用Scroll或Search After分頁方式,相比之下最好使用Search After方式,既可以保證資料的實時性,也具有很高的搜索性能,
  • 總之,在使用ES時一定要避免深度分頁問題,要在跳頁功能實作和ES性能、資源之間做一個取舍,必要時也可以調大max_result_window引數,原則上不建議這么做,因為1w條以內ES基本能保持很不錯的性能,超過這個范圍深度分頁相當耗時、耗資源,因此謹慎選擇此方式,

作者:何守優

轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/534208.html

標籤:其它

上一篇:資料庫獨角獸SingleStore:沒有HTAP,機器學習和人工智能都是不切實際的

下一篇:還在為資料庫事務一致性檢測而苦惱?讓Elle幫幫你,以TDSQL為例我們測測 | DB·洞見#7

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • GPU虛擬機創建時間深度優化

    **?桔妹導讀:**GPU虛擬機實體創建速度慢是公有云面臨的普遍問題,由于通常情況下創建虛擬機屬于低頻操作而未引起業界的重視,實際生產中還是存在對GPU實體創建時間有苛刻要求的業務場景。本文將介紹滴滴云在解決該問題時的思路、方法、并展示最終的優化成果。 從公有云服務商那里購買過虛擬主機的資深用戶,一 ......

    uj5u.com 2020-09-10 06:09:13 more
  • 可編程網卡芯片在滴滴云網路的應用實踐

    **?桔妹導讀:**隨著云規模不斷擴大以及業務層面對延遲、帶寬的要求越來越高,采用DPDK 加速網路報文處理的方式在橫向縱向擴展都出現了局限性。可編程芯片成為業界熱點。本文主要講述了可編程網卡芯片在滴滴云網路中的應用實踐,遇到的問題、帶來的收益以及開源社區貢獻。 #1. 資料中心面臨的問題 隨著滴滴 ......

    uj5u.com 2020-09-10 06:10:21 more
  • 滴滴資料通道服務演進之路

    **?桔妹導讀:**滴滴資料通道引擎承載著全公司的資料同步,為下游實時和離線場景提供了必不可少的源資料。隨著任務量的不斷增加,資料通道的整體架構也隨之發生改變。本文介紹了滴滴資料通道的發展歷程,遇到的問題以及今后的規劃。 #1. 背景 資料,對于任何一家互聯網公司來說都是非常重要的資產,公司的大資料 ......

    uj5u.com 2020-09-10 06:11:05 more
  • 滴滴AI Labs斬獲國際機器翻譯大賽中譯英方向世界第三

    **桔妹導讀:**深耕人工智能領域,致力于探索AI讓出行更美好的滴滴AI Labs再次斬獲國際大獎,這次獲獎的專案是什么呢?一起來看看詳細報道吧! 近日,由國際計算語言學協會ACL(The Association for Computational Linguistics)舉辦的世界最具影響力的機器 ......

    uj5u.com 2020-09-10 06:11:29 more
  • MPP (Massively Parallel Processing)大規模并行處理

    1、什么是mpp? MPP (Massively Parallel Processing),即大規模并行處理,在資料庫非共享集群中,每個節點都有獨立的磁盤存盤系統和記憶體系統,業務資料根據資料庫模型和應用特點劃分到各個節點上,每臺資料節點通過專用網路或者商業通用網路互相連接,彼此協同計算,作為整體提供 ......

    uj5u.com 2020-09-10 06:11:41 more
  • 滴滴資料倉庫指標體系建設實踐

    **桔妹導讀:**指標體系是什么?如何使用OSM模型和AARRR模型搭建指標體系?如何統一流程、規范化、工具化管理指標體系?本文會對建設的方法論結合滴滴資料指標體系建設實踐進行解答分析。 #1. 什么是指標體系 ##1.1 指標體系定義 指標體系是將零散單點的具有相互聯系的指標,系統化的組織起來,通 ......

    uj5u.com 2020-09-10 06:12:52 more
  • 單表千萬行資料庫 LIKE 搜索優化手記

    我們經常在資料庫中使用 LIKE 運算子來完成對資料的模糊搜索,LIKE 運算子用于在 WHERE 子句中搜索列中的指定模式。 如果需要查找客戶表中所有姓氏是“張”的資料,可以使用下面的 SQL 陳述句: SELECT * FROM Customer WHERE Name LIKE '張%' 如果需要 ......

    uj5u.com 2020-09-10 06:13:25 more
  • 滴滴Ceph分布式存盤系統優化之鎖優化

    **桔妹導讀:**Ceph是國際知名的開源分布式存盤系統,在工業界和學術界都有著重要的影響。Ceph的架構和演算法設計發表在國際系統領域頂級會議OSDI、SOSP、SC等上。Ceph社區得到Red Hat、SUSE、Intel等大公司的大力支持。Ceph是國際云計算領域應用最廣泛的開源分布式存盤系統, ......

    uj5u.com 2020-09-10 06:14:51 more
  • es~通過ElasticsearchTemplate進行聚合~嵌套聚合

    之前寫過《es~通過ElasticsearchTemplate進行聚合操作》的文章,這一次主要寫一個嵌套的聚合,例如先對sex集合,再對desc聚合,最后再對age求和,共三層嵌套。 Aggregations的部分特性類似于SQL語言中的group by,avg,sum等函式,Aggregation ......

    uj5u.com 2020-09-10 06:14:59 more
  • 爬蟲日志監控 -- Elastc Stack(ELK)部署

    傻瓜式部署,只需替換IP與用戶 導讀: 現ELK四大組件分別為:Elasticsearch(核心)、logstash(處理)、filebeat(采集)、kibana(可視化) 下載均在https://www.elastic.co/cn/downloads/下tar包,各組件版本最好一致,配合fdm會 ......

    uj5u.com 2020-09-10 06:15:05 more
最新发布
  • day02-2-商鋪查詢快取

    功能02-商鋪查詢快取 3.商鋪詳情快取查詢 3.1什么是快取? 快取就是資料交換的緩沖區(稱作Cache),是存盤資料的臨時地方,一般讀寫性能較高。 快取的作用: 降低后端負載 提高讀寫效率,降低回應時間 快取的成本: 資料一致性成本 代碼維護成本 運維成本 3.2需求說明 如下,當我們點擊商店詳 ......

    uj5u.com 2023-04-20 08:33:24 more
  • MySQL中binlog備份腳本分享

    關于MySQL的二進制日志(binlog),我們都知道二進制日志(binlog)非常重要,尤其當你需要point to point災難恢復的時侯,所以我們要對其進行備份。關于二進制日志(binlog)的備份,可以基于flush logs方式先切換binlog,然后拷貝&壓縮到到遠程服務器或本地服務器 ......

    uj5u.com 2023-04-20 08:28:06 more
  • day02-短信登錄

    功能實作02 2.功能01-短信登錄 2.1基于Session實作登錄 2.1.1思路分析 2.1.2代碼實作 2.1.2.1發送短信驗證碼 發送短信驗證碼: 發送驗證碼的介面為:http://127.0.0.1:8080/api/user/code?phone=xxxxx<手機號> 請求方式:PO ......

    uj5u.com 2023-04-20 08:27:27 more
  • 快取與資料庫雙寫一致性幾種策略分析

    本文將對幾種快取與資料庫保證資料一致性的使用方式進行分析。為保證高并發性能,以下分析場景不考慮執行的原子性及加鎖等強一致性要求的場景,僅追求最終一致性。 ......

    uj5u.com 2023-04-20 08:26:48 more
  • sql陳述句優化

    問題查找及措施 問題查找 需要找到具體的代碼,對其進行一對一優化,而非一直把關注點放在服務器和sql平臺 降低簡化每個事務中處理的問題,盡量不要讓一個事務拖太長的時間 例如檔案上傳時,應將檔案上傳這一步放在事務外面 微軟建議 4.啟動sql定時執行計劃 怎么啟動sqlserver代理服務-百度經驗 ......

    uj5u.com 2023-04-20 08:26:35 more
  • 云時代,MySQL到ClickHouse資料同步產品對比推薦

    ClickHouse 在執行分析查詢時的速度優勢很好的彌補了MySQL的不足,但是對于很多開發者和DBA來說,如何將MySQL穩定、高效、簡單的同步到 ClickHouse 卻很困難。本文對比了 NineData、MaterializeMySQL(ClickHouse自帶)、Bifrost 三款產品... ......

    uj5u.com 2023-04-20 08:26:29 more
  • sql陳述句優化

    問題查找及措施 問題查找 需要找到具體的代碼,對其進行一對一優化,而非一直把關注點放在服務器和sql平臺 降低簡化每個事務中處理的問題,盡量不要讓一個事務拖太長的時間 例如檔案上傳時,應將檔案上傳這一步放在事務外面 微軟建議 4.啟動sql定時執行計劃 怎么啟動sqlserver代理服務-百度經驗 ......

    uj5u.com 2023-04-20 08:25:13 more
  • Redis 報”OutOfDirectMemoryError“(堆外記憶體溢位)

    Redis 報錯“OutOfDirectMemoryError(堆外記憶體溢位) ”問題如下: 一、報錯資訊: 使用 Redis 的業務介面 ,產生 OutOfDirectMemoryError(堆外記憶體溢位),如圖: 格式化后的報錯資訊: { "timestamp": "2023-04-17 22: ......

    uj5u.com 2023-04-20 08:24:54 more
  • day02-2-商鋪查詢快取

    功能02-商鋪查詢快取 3.商鋪詳情快取查詢 3.1什么是快取? 快取就是資料交換的緩沖區(稱作Cache),是存盤資料的臨時地方,一般讀寫性能較高。 快取的作用: 降低后端負載 提高讀寫效率,降低回應時間 快取的成本: 資料一致性成本 代碼維護成本 運維成本 3.2需求說明 如下,當我們點擊商店詳 ......

    uj5u.com 2023-04-20 08:24:03 more
  • day02-短信登錄

    功能實作02 2.功能01-短信登錄 2.1基于Session實作登錄 2.1.1思路分析 2.1.2代碼實作 2.1.2.1發送短信驗證碼 發送短信驗證碼: 發送驗證碼的介面為:http://127.0.0.1:8080/api/user/code?phone=xxxxx<手機號> 請求方式:PO ......

    uj5u.com 2023-04-20 08:23:11 more