偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

架構師必備:多維度查詢的優(yōu)秀實踐

開發(fā) 架構 數(shù)據(jù)庫
普通的數(shù)據(jù)庫查詢,很難實現(xiàn)上述需求場景,更不用提模糊查詢、全文檢索了。

背景

有2種常見的多維度查詢場景,分別是:

  • 帶多個篩選條件的列表查詢
  • 不含分庫分表列的其他維度查詢

普通的數(shù)據(jù)庫查詢,很難實現(xiàn)上述需求場景,更不用提模糊查詢、全文檢索了。

下面結合樓主的經(jīng)驗和知識,介紹初級方案、進階方案(上ElasticSearch),大部分情況下推薦使用ElasticSearch來實現(xiàn)多維度查詢,趕時間的讀者可以直接跳到“進階方案:將ElasticSearch添加到現(xiàn)有系統(tǒng)中”。

初級方案

1、根據(jù)常見查詢場景,增加相應字段的組合索引

這個是為了實現(xiàn)帶多個篩選條件的列表查詢的。

優(yōu)點

  • 非常簡單
  • 讀寫不一致時間較短:取決于數(shù)據(jù)庫主從同步延時,一般為毫秒級別

缺點

  • 非常局限:除非篩選條件比較固定,否則難以應付后續(xù)新增或修改篩選條件
  • 如果每次來新的篩選查詢字段的需求,就新增索引,最終導致索引過于龐大,影響性能

于是就出現(xiàn)了經(jīng)典的一幕:產(chǎn)品提需求說要支持某個新字段的篩選查詢,開發(fā)反饋說做不了、或者成本很高,于是不了了之 :)

2、異構出多份數(shù)據(jù)

更加優(yōu)雅的方式,是異構出多份數(shù)據(jù)。

例如,C端按用戶維度查詢,B端按店鋪維度查詢,如果還有供應商,按供應商維度查詢。一個數(shù)據(jù)庫只能按一種維度來分庫。

(1)程序寫入多個數(shù)據(jù)源

優(yōu)點是:非常簡單。

缺點

  • 跨庫寫存在一致性問題(除非不同維度的表使用公共的分庫,事務寫入),性能低
  • 不能靈活支持更多其他維度的查詢

(2)借助Canal實現(xiàn)數(shù)據(jù)的自動同步

通過Canal同步數(shù)據(jù),異構出多個維度的數(shù)據(jù)源。詳見之前寫的這篇文章: 架構師必備:巧用Canal實現(xiàn)異步、解耦的架構

優(yōu)點是:更加優(yōu)雅,無需改動程序主流程。

缺點

  • 仍然無法解決不斷變化的需求,不可能為了支持新維度就異構出一份新數(shù)據(jù)

進階方案:將ElasticSearch添加到現(xiàn)有系統(tǒng)中

應用架構

現(xiàn)有系統(tǒng)一般都會用到MySQL數(shù)據(jù)庫,需要引入ES,為系統(tǒng)增強多維度查詢的功能。

MySQL繼續(xù)承擔業(yè)務的實時讀寫請求、事務操作,ES承擔近實時的多維度查詢請求,ES可支撐十萬級別qps(取決于節(jié)點數(shù)、分片數(shù)、副本數(shù))。

需要注意的是:同步數(shù)據(jù)至ES是秒級延遲(主要耗費在索引refresh),而查詢已進入索引的文檔,是在數(shù)毫秒到數(shù)百毫秒級別。

導入數(shù)據(jù)

需要同步機制,來把MySQL中的數(shù)據(jù)導入到ES中,主要流程如下:

  • 預先定義ES索引的mapping配置,而不依賴ES自動生成mapping
  • 初始全量導入,后續(xù)增量導入:Canal+MQ數(shù)據(jù)管道同步,不需要或僅需少量代碼工作
  • 數(shù)據(jù)過濾:不導入無需檢索的字段,減小索引大學,提高性能
  • 數(shù)據(jù)扁平化處理:如果數(shù)據(jù)庫中有json字段列,需要從中提取業(yè)務字段,避免嵌套類型的字段,提高性能

查詢數(shù)據(jù)

  • 從ES 8.x版本開始,建議使用Java api client,并且要Java 8及以上環(huán)境,因為可使用各種lambda函數(shù),來提高代碼可讀性
  • 優(yōu)點是新客戶端與server代碼完全耦合(相比于原Java transport client,在8.x版本已廢棄),并且API風格與http rest api很接近(相比于原Java rest client,在8.x版本已廢棄),只要熟練掌握http json請求體寫法,即可快速上手。
  • 底層使用的還是原來的low level rest client,實現(xiàn)了http長連接、訪問ES各節(jié)點的負載均衡、故障轉移,最底層依賴的是apache http async client。
  • ES 7.x版本及以下,或使用Java 7及以下,建議升級,否則就只能繼續(xù)用high level rest client。

代碼示例如下(含詳細注釋):

public class EsClientDemo {

// demo演示:創(chuàng)建client,然后搜索
public void createClientAndSearch() throws Exception {
// 創(chuàng)建底層的low level rest client,連接ES節(jié)點的9200端口
RestClient restClient = RestClient.builder(
new HttpHost("localhost", 9200)).build();

// 創(chuàng)建transport類,傳入底層的low level rest client,和json解析器
ElasticsearchTransport transport = new RestClientTransport(
restClient, new JacksonJsonpMapper());

// 創(chuàng)建核心client類,后續(xù)操作都圍繞此對象
ElasticsearchClient esClient = new ElasticsearchClient(transport);


// 多條件搜索
// fluent API風格,并且使用lambda函數(shù)提高代碼可讀性,可以看出Java api client的語法,同http json請求體非常相似
String searchText = "bike";
String brand = "brandNew";
double maxPrice = 1000;

// 根據(jù)商品名稱,做match全文檢索查詢
Query byName = MatchQuery.of(m -> m
.field("name")
.query(searchText)
)._toQuery();

// 根據(jù)品牌,做term精確查詢
Query byBrand = new Query.Builder()
.term(t -> t
.field("brand")
.value(v -> v.stringValue(brand))
).build();

// 根據(jù)價格,做range范圍查詢
Query byMaxPrice = RangeQuery.of(r -> r
.field("price")
.lte(JsonData.of(maxPrice))
)._toQuery();

// 調用核心client,做查詢
SearchResponse<Product> response = esClient.search(s -> s
.index("products") // 指定ES索引
.query(q -> q // 指定查詢DSL
.bool(b -> b // 多條件must組合,必須同時滿足
.must(byName)
.must(byBrand)
.must(byMaxPrice)
)
),
Product.class
);

// 遍歷命中結果
List<Hit<Product>> hits = response.hits().hits();
for (Hit<Product> hit: hits) {
Product product = hit.source(); // 通過source獲取結果
logger.info("Found product " + product.getName() + ", score " + hit.score());
}
}

}

可參閱: ??https://www.elastic.co/guide/en/elasticsearch/client/index.html??

數(shù)據(jù)模型轉換

因為既有MySQL,又有ES,所以有2種異構的數(shù)據(jù)模型。需要在代碼中定義2種數(shù)據(jù)模型,并且實現(xiàn)類型互相轉換的工具類。

  • MySQL數(shù)據(jù)VO
  • ES數(shù)據(jù)VO
  • MySQL數(shù)據(jù)VO、ES數(shù)據(jù)VO互相轉換工具
  • 業(yè)務層BO
  • 接口DTO

原理概要

ES之所以比MySQL,能勝任多維度查詢、全文檢索,是因為底層數(shù)據(jù)結構不同:

  • ES倒排索引
  • 如果是全文檢索字段:會先分詞,然后生成 term -> document 的倒排索引,查詢時也會把query分詞,然后檢索出相關的文檔。相關度算法如TF-IDF(term frequency–inverse document frequency),取決于:詞在該文檔中出現(xiàn)的頻率(TF,term frequency),越高代表越相關;以及詞在所有文檔中出現(xiàn)的頻率(IDF,inverse document frequency),越高代表越不相關,相當于是一個通用的詞,對相關性影響較小。
  • 如果是精確值字段:則無需分詞,直接把query作為一個整體的term,查詢對應文檔。
  • 因為文檔中的所有字段,都生成了倒排索引,所以能處理多維度組合查詢
  • MySQL B+樹
  • B+樹的非葉子節(jié)點記錄了孩子節(jié)點值的范圍,而葉子節(jié)點記錄了真正的一組值,并且在同一層,形成了一個有序鏈表
  • 組合索引需要顯式創(chuàng)建:選擇需索引的字段、并且順序是重要的,所以如果待查詢的字段不在索引中,就無法高效查詢,可能演變?yōu)槿頀呙?/span> (對聚簇索引的葉子節(jié)點做一次遍歷)

另外簡要回顧一下ES的架構要點:

  • 節(jié)點分為主節(jié)點、數(shù)據(jù)節(jié)點,一個節(jié)點上可以有多個分片,分片分為主分片、副本分片,1對多,主分片與副本分片分布在不同的節(jié)點,來實現(xiàn)高可用
  • 主分片數(shù)在創(chuàng)建時,就需要指定,在創(chuàng)建后不能隨意更改(如果變化,路由就會出錯);而副本分片可以增加,來提高ES集群的查詢QPS
  • 路由算法:id % 主分片數(shù),如果創(chuàng)建文檔時不指定id,則ES會自動生成;一般會傳自定義業(yè)務id

優(yōu)點、缺點

優(yōu)點

  • 支持各字段的多維度組合查詢,無懼未來新增字段(主要成本在于新增字段后、重建索引)
  • 與現(xiàn)有系統(tǒng)完全解耦,適合架構演進
  • 在數(shù)據(jù)量級上遠勝Mysql,最大支持PB級數(shù)據(jù)的存儲和查詢

缺點

  • 讀寫不一致時間在秒級:因為有2個耗時階段,一是同步階段將數(shù)據(jù)從MySQL數(shù)據(jù)庫寫入ES,二是ES索引refresh階段,數(shù)據(jù)從buffer寫入索引后才可查到
  • 因此一個trick就是,在寫入操作后,前端延遲調用后端的列表查詢接口,比如延遲1秒后再展示
  • 超高并發(fā)下存在瓶頸,存在穩(wěn)定性問題:目前原生版本支持大約 3-5 萬分片,性能已經(jīng)到達極限,創(chuàng)建索引基本到達 30 秒+ 甚至分鐘級。節(jié)點數(shù)只能到 500 左右基本是極限了。但依然能滿足絕大部分場景。數(shù)據(jù)來源: ??https://elasticsearch.cn/slides/259#page=30??

ES最佳實踐

  • 只把需要搜索的數(shù)據(jù)導入ES,避免索引過大
  • 數(shù)據(jù)扁平化,不用嵌套結構,提高性能
  • 合理設置字段類型,預先定義mapping配置,而不依賴ES自動生成mapping
  • 精確值的類型指定為keyword(mapping配置),并且使用term查詢
  • 精確值是指無需進行range范圍查詢的字段,既可以是字符串,比如書的作者名字,也可以是數(shù)值,比如商品id、訂單id、圖書ISBN編號、枚舉值。在使用中,大部分場景是以id類作為精確值
  • 避免無路由查詢:無路由查詢會并發(fā)在多個索引上查詢、歸并排序結果,會使得集群cpu飆升,影響穩(wěn)定性
  • 避免深度分頁查詢:如有大量數(shù)據(jù)查詢,推薦用scroll滾動查詢
  • 設置合理的文件系統(tǒng)緩存(filesytem cache)大小,提高性能:因為ES查詢的熱數(shù)據(jù)在文件系統(tǒng)緩存中
  • ES分片數(shù)在創(chuàng)建后不能隨意改動,但是副本數(shù)可以隨時增加,來提高最大QPS。如果單個分片壓力過大,需要擴容。

更進一步

前面提到ES超高并發(fā)下存在瓶頸,極端情況下可能遇到OOM,因此超高并發(fā)下需要C++實現(xiàn)的專用搜索引擎

例如:

  • 百度:通用搜索引擎,根據(jù)文字、圖片搜索信息
  • 電商垂類:電商專用搜索引擎,比如根據(jù)關鍵詞查找商品,或根據(jù)品牌、價格篩選商品,可總結為商品的搜索、廣告、推薦
責任編輯:張燕妮 來源: 博客園
相關推薦

2022-08-29 09:14:01

戰(zhàn)略設計核心域支撐域

2022-05-27 15:19:38

架構師溝通認知

2023-12-01 07:24:40

軟件架構

2015-06-10 11:22:41

云計算云架構師

2015-12-23 10:50:24

運維OPS運維架構師

2019-10-30 16:24:34

分層架構緩存

2012-08-13 16:48:31

架構師

2023-10-07 14:25:14

2021-10-09 09:52:49

MYSQL開發(fā)數(shù)據(jù)庫

2023-09-27 10:23:19

NoSQL數(shù)據(jù)模型

2019-07-16 13:59:43

數(shù)據(jù)庫MySQL軟件

2021-10-22 08:00:00

架構開發(fā)技術

2013-01-28 14:59:27

2020-08-24 08:50:12

架構師TL技術

2024-01-04 09:00:00

SQL數(shù)據(jù)庫開發(fā)

2013-06-13 14:29:26

架構師程序員

2018-05-14 09:00:23

NB架構師素質

2019-05-21 10:45:44

Docker架構容器

2009-12-18 10:22:50

Ray Ozzie架構師

2019-07-03 10:28:24

架構師系統(tǒng)IT
點贊
收藏

51CTO技術棧公眾號