互聯網大廠的後端技術棧

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

程序員的成長之路前端

互聯網/程序員/技術/資料共享 java

閱讀本文大概須要 17 分鐘。node

做者:文西nginx

最近公司招聘海外後端研發,因此整理一份技術棧的資料給他們,可是想來這份整理也適用於全部後端研發,因此去掉了敏感內容,把它呈現於此。程序員

本文重在概述,畢竟篇幅有限,歡迎「關注」,後續可能把單點拓展成文,詳細地一一闡述,另外筆者見識有限,畢竟也沒有可能在全部大廠工做過,因此若是有疏漏能夠在留言處賜教。web

目錄:算法

後端開發概述spring

負載均衡sql

微服務生態數據庫

  • Thrift

  • 服務發現

    • Consul

    • 微服務框架

數據庫

  • Mysql

  • Mycat

  • DRC

緩存(Cache)

  • Redis

  • Redis集羣化方案

KV-DB

消息隊列

  • RocketMQ

  • Kafka

對象存儲

Elastic Search

後端開發概述

何爲後端開發?以一個網站爲例,一般來講,前端研發注重頁面的展現,交互邏輯。然後端研發,則注重在發生在前端背後(backend)的邏輯上,例如給前端返回數據,存儲數據。

對於一個電商網站,一個簡單的下單動做,後端可能包括商品數據查詢,優惠信息計算,庫存維護,用戶優惠券維護,訂單生成,商家通知觸發等等。在不少大公司先後端的配比是1:3甚至更高,由於一個複雜的業務系統,前端的展現僅僅是冰山一角,更復雜的業務邏輯都隱藏在後端。

一般來講,當用戶觸發某個行爲後,客戶端會經過http/https請求,和咱們的服務器創建鏈接,發送請求,每每這個請求首先會被連接到負載均衡(LB)上,負載均衡根據配置,將請求轉發到內部的API服務上。

這些API服務,根據不一樣的業務邏輯會請求其餘服務(Service),這些服務各司其職,例如讀寫某 Mysql 表、讀寫緩存,甚至請求搜索引擎來完成相應的任務。

而API服務在完成相應的步驟後,也會將數據返回給客戶端,客戶端根據前端邏輯完成相關的展現。

下面這個圖,簡單的展現了服務端研發可能使用服務組織方式和相關技術棧,後續會對全部技術棧和大廠使用場景一一簡述。

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

負載均衡 - Load Balance(LB)

負載均衡做爲鏈接內外的門戶,在分佈式系統中,有這很是核心的做用。下面的圖是負載均衡最直觀的呈現:

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

它將流量從外部轉發到內部系統,對於一樣的請求內容,不一樣時序的請求會被轉發到不一樣的服務實例上。

對每一個服務實例而言,它只須要承擔系統總流量的  1/N 從而下降了單個服務的負載,提高了服務總體相應速度和系統穩定性。負載均衡器會保持跟蹤全部下游服務的狀態,若是服務不可用,則會被從調度移除。

一個最經常使用的負載均衡就是Nignx反向代理,在上圖中,若是使用Nginx作負載均衡,最簡單的方法就是配置 upstream,例以下:

#配置負載均衡實例
upstream user_api {
   server 10.0.6.108:7080;
   server 10.0.0.85:8980;
}

#配置轉發到 user_api upstream
location /user {
    proxy_pass http://user_api;
}


顯然,這份配置中要指定 user api 服務已經部署實例的 IP 地址和端口。若是沒有自動化的發佈方案,意味着每次開發新的API都須要在服務發佈好之後,更新 Nginx 配置,而後經過 reload nginx 的方式將API發佈上線。

若是API不常常變更,這種作法也能支撐業務發展;可是若是公司業務快速發展,常常頻繁發佈API風險就會比較大了。

在服務重啓切換配置的過程當中,可能致使一些請求處理被丟棄,就連服務擴容和縮容(增長減小負載均衡實例),也要變動相應的nginx配置。

因此不少大廠,都會建設本身的 LB 平臺,在這裏你能夠配置須要暴露出去的 URL,提供服務的內部服務標識,也會支持一些額外的配置,包括限流、熔斷參數等。

而要作到這些,每每須要對 Nginx 原生的負載均衡能力作拓展,例如使用 dyups 模塊支持動態上下線配置;須要一個額外的管理平臺,來管理全部對外API;須要服務註冊中心維護全部的服務對應的集羣和實例。

同時須要啓動一個 API Watch的在線常駐服務,負責監聽API配置變動和註冊中心每一個服務實例的上下線變動,生成 dyups 模塊能夠識別的 Nginx 配置,在線 load 到 Nginx 就能夠完成服務動態上下線了。原理以下圖:

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

固然,這只是一個最基本的功能和原理展現,大廠們每每根據不一樣的在線使用場景會有不少優化和系統設計的考量。

微服務生態

微服務 - 也被稱爲微服務架構 - 一種將整個後端服務,按照領域、模塊分解爲若干獨立小應用的一種架構方式。

微服務有以下特色:

  • 服務能夠單獨編寫、發佈、測試、部署,相比於全部功能集中於一體的單體服務,可維護性更強

  • 服務彼此之間依賴服務通訊的方式鬆耦合

  • 按照業務領域來組織服務,每一個團隊維護各自的服務

下圖直觀的闡述微服務的概念:

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

既然微服務體系是按照組織結構、功能模塊獨立進行開發、測試、部署的,那麼微服務架構就要解決由於獨立部署帶來一些問題,例如通信協議,遠程調用(RPC),服務發現,服務治理等。

有能力的大廠每每會有本身的框架來解決上面的問題,例如淘寶的HSF、阿里開源的 dubbo,能力不足的小廠也能夠從開源社區中選擇合適技術爲我所用,「拼湊」出合理的解決方案,下面主要從開源社區選擇一些可用爲我所用的技術來介紹。

Thrift

Thrift不只僅是一個輕量的,高性能的遠程調用(RPC)通信協議,也是一個優秀的RPC框架。Thrift 使用一種被稱爲 IDL 的接口定義語言,來定義遠程調用的接口。

使用官方提供的工具能夠將IDL文件生成微服務服務端(Server)和客戶端(Client)代碼。這裏 Server 端指提供服務的一方,而 Client 則指服務調用方,Client 經過 RPC 對 Server進行調用。

利用這份生成的代碼,就能夠實現Client經過指定IP和端口的調用Server服務了。我的感受 Thrift 最大的優點是高性能,跨語言,以及足夠輕量。跨語言是很好的特性,由於一個大公司的不一樣部門,可能語言技術棧會有差別,使用 Thrift 能夠屏蔽這種差別,讓彼此專一。

服務發現

上面提到,若是隻依賴 Thrift 咱們能夠實現經過指定IP端口的方式進行服務調用,可是顯然這是不可行的,咱們須要 Client 動態感知 Server 端服務的存在以及提供服務的全部實例。

服務註冊中心就是解決這個問題而誕生的概念,能夠簡單理解註冊中心就是一個保存着服務狀態的」數據庫「,服務成功啓動後到註冊中心去註冊,而且保持和註冊中心的心跳以維持服務在註冊中心的最新狀態,當服務下線或者異常退出,服務能夠主動通知註冊中心下線或者被註冊中心經過心跳失敗感知到。

常見的服務註冊中心例如 Spring Cloud 框架中官方提供的 Eureka,Dubbo 默認使用的 Zookeeper。Spring Cloud 和 Dubbo 也對 Consul 增長了原生支持,這裏也主要介紹下Consul。具體對比能夠參考[1]

Consul

Consul是基於GO語言開發的開源工具,主要面向分佈式,服務化的系統提供服務註冊、服務發現和配置管理的功能。

Consul的功能都很實用,其中包括:服務註冊/發現、健康檢查、Key/Value存儲、多數據中心和分佈式一致性保證等特性。Consul自己只是一個二進制的可執行文件,因此安裝和部署都很是簡單,只須要從官網下載後,在執行對應的啓動腳本便可。

若是使用 Spring Cloud 或者 Dubbo 等微服務框架,能夠經過配置實現使用 Consul 做爲服務註冊中心,服務啓動後,在Consul提供的Web界面就能夠查到相應的服務。

服務客戶端能夠在第一次調用服務端前,經過Consul進行服務端實例的查詢而後按照查詢奧的服務實例進行遠程調用。

Consul 的 web界面:

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

微服務框架

開源社區中知名的微服務框架包括 Spring Cloud, Dubbo 等,這些框架配合生態中的一切其餘組件能夠解決例如服務註冊&發現、負載均衡、熔斷限流、調用鏈追蹤等絕大多數問題。

不過當業務發展到必定階段,還會有更多問題要解決,例如服務調用鑑權等問題。

因此各個大廠幾乎都自研本身的微服務框架,可是基本的作法都是在開源社區選擇一部分,本身擴展一部分,例如通信協議和RPC選擇Thrift,服務註冊中心選 Zookeeper/Consul,而後須要自研擴展的部分就是例如服務註冊,服務發現,負載均衡,統一監控,鑑權等公司特點的需求。

數據庫(Database)

對於一個小公司而言,可能會選擇把全部數據保存在 Mysql 中,由於所有業務數據的容量可能也只有百G。

可是對於大廠,天天產生的數據可能都是T級別的,若是都保存在Mysql中會有諸多問題,例如存儲成本、後續的修改查詢效率、高併發場景下存儲的極限能力等。

數據有它不一樣業務特性和使用場景,業務特性很好理解,例如咱們不容忍交易數據發生丟失而且在不少操做它的場景,要求強一致性;而用戶評論,則能容忍很小比例丟失,而且評論計數器和評論數目以前的若是出現微小差距,用戶也很難察覺到;而服務日誌數據,則能容忍更大程度的丟失,只要不影響開發Debug可能就不會有人追究。

數據不一樣的使用場景,也對存儲有不一樣方面的要求。例如一樣是用戶資料,用戶資料查看本身的資料,必定要保證資料是用戶最新更新的,而且不能容忍出錯,哪怕是頁面相應速度略微慢一點;可是用在推薦場景做爲用戶畫像做爲模型輸入的時候,就能容忍這個數據不是最新的,可是要求數據訪問速度要高,由於推薦場景每每對成千上萬個候選排序,畫像數據訪問慢則直接拖累了整個推薦系統的效率。

Mysql

對於Web應用而言,關係型數據庫的選型中 Mysql 無疑是最佳選擇。它體積小、速度快、開源受權使得它擁有成本低,支持多種操做系統,有豐富的社區支持,支持多種語言鏈接和操做。

Mysql是保存業務數據的理想之選,首先關係型數據庫在設計之初,從概念上就在支持業務數據建模的概念,關係型數據庫能結構化的描述業務需求。Mysql 對ACID屬性的支持,也能知足不一樣業務場景下對數據操做的不一樣訴求。可是在大廠背景下,Mysql也有它的限制。

首先,對於在線大表DDL幾乎不太可能,DDL指表結構變動之類的操做。對於一張動輒幾千萬數據的表,Alter Table 可能須要幾小時,除非提供備案方案,不然服務在這段時間將不可用。

其次,在線查詢要注意性能優化,避免慢SQL拖垮DB的場景。常見的性能問題包括查詢未命中索引而觸發全表掃描;使用了聚合查詢(group by)觸發全表掃描等。

還有,大廠特別是ToC常見的大廠,天天產生的業務數據異常的大,Mysql存儲超過幾千萬性能會降低,因此須要使用分庫分表的方式來解決海量數據場景下的存儲問題。

Mycat

Mycat就是一個解決數據庫分庫分表等問題的數據庫中間件,也能夠理解爲是數據庫代理。在架構體系中是位於數據庫和應用層之間的一個組件,Mycat 實現了 Mysql 的原生協議,對於應用它感知不到鏈接了 Mycat,由於從協議來說,二者是同樣的。

而Mycat將應用的請求轉發給它後面的數據庫,對應用屏蔽了分庫分表的細節。Mycat的三大功能:分表、讀寫分離、主從切換。

下圖經過 Mycat schema 配置和實際 DB 部署來簡要說明 Mycat 分庫分表功能的實現:

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

例如表 A,配置中它有兩個數據節點,分別是  datanode1 和 datanode2,含義是邏輯表 A實際對應了兩個物理存儲,分別是 db1 和 db2。對於應用而言,應用鏈接 Mycat 感知到的時候邏輯表 A,而在底層 A 被拆分,存儲在兩個 db 中。

DRC

DRC 是 Data Replication Center 的縮寫,在使用Mysql做爲核心存儲的場景下,咱們可使用Mysql原生的主備方案,實現同城災備。可是若是 Mysql 部署在跨國,跨洲的場景下,原生的災備方案就有諸多問題了,因此各大廠幾乎都有本身的DRC方案。

不過,雖然各自有不一樣的實現,可是原理和依賴的核心組件基本相同,本文從互聯網上找到餓了麼DRC組件闡述其原理。

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

本圖中,異地機房分別爲北京機房和上海機房。本地機房(圖中爲北京機房)會啓動一個 DRC Replicator,它和Master節點通訊並在通訊協議上模擬 Mysql Slave,Replicator將Master數據庫的binlog變動實時拉取到本地。

而後把binlog解析,經過消息中間件將變動發送到異地機房(北京機房)。

異地機房啓動一個DRC Applier的應用消費數據變動消息,而後把這個變動操做同步到本機房的Master上,就完成了異地數據同步的操做。圖中展現的是北京機房數據同步到上海機房的場景,實際反過來也是同樣。

DRC在設計和實踐中最多見的問題就是DB自增類型主鍵衝突,以及數據由於同步消息丟失而最後致使的不一致,前者能夠經過強制使用ID生成器或者自增ID設置相同的增長值和不一樣的初始值等方式解決。

然後者要麼採用一個規則同步最終數據,或者進行人爲數據干預。

緩存(Cache)

若是稍微深刻研究Mysql的存儲原理,咱們不難發現,數據是存儲在磁盤中的,雖然咱們能夠經過索引等數據結構,下降每次查找數據的響應時間,可是對於高併發的在線應用,直接查找數據庫依然很容易觸碰Mysql性能瓶頸,因此咱們須要緩存來緩解DB查詢的壓力,當要查詢的數據命中緩存後,直接從緩存中獲取數據,從而下降DB的訪問壓力。常見的緩存有兩種策略:

本地緩存:不須要序列化,速度快,緩存的數量與大小受限於本機內存,不少語言提供一些框架來支持內存緩存,例如 guava cache,spring默認集成的 Ehcache。

分佈式緩存:須要序列化,速度相較於本地緩存較慢,可是理論上緩存的數量與容量無限制(由於分佈式緩存機器能夠不斷擴展),常見的分佈式緩存包括 Redis 和 Memcache。本文主要介紹下 Redis。

Redis

Redis 是基於內存的緩存中間件,正由於基於內存,因此具備很是快的相應速度。支持豐富的數據結構,例如 string、hashes、list、set、sorted set等等,應用很是普遍的應用。

常見的緩存讀寫策略包括Cache-Aside,Read Through,Write Through,具體能夠參考[2],不過文中缺乏一種Cache 讀寫方案,這也是不少高併發在線應用比較經常使用的一種方式。

Write Behind Caching模式

Write Behind Caching 這種模式一般是先將數據寫入到緩存裏面,而後再異步地將DB更新的數據寫入到cache中,這樣的設計既能夠直接的減小咱們對於數據的database裏面的直接訪問,下降壓力,同時對於database的屢次修改能夠進行合併操做,極大的提高了系統的承載能力。

這個模式下,應用在讀數據的時候,不感知DB,只感知Cache,優點在於簡化了設計,缺點在於強依賴Cache,若是Cache出現問題例如宕機,則讀會失效。

Redis 集羣方案

伴隨着須要緩存的數據量增長和高可用的依賴,大廠的Redis都是須要集羣化方式部署的。一方面經過主從模式提高了系統的高可用,另外一方面經過集羣模式將系統演化爲可用無限擴容的模式。

Redis 從 3.0 版本開始,原生的支持了集羣模式,經過 Sentinel 集羣實現動態的主從模式[3];原生的集羣模式,將全部的數據劃分到 16384 slots中,而集羣中的每一個節點,會分配若干 slots。

然而原生集羣的方案,雖然簡化了集羣的設計,可是卻增長了客戶端的負擔,須要客戶端對Moved/ASK [4] 事件作封裝處理,同時須要維護路由表提升訪問效率,增長了客戶端設計的複雜度。

因此大廠每每不會選擇 Redis 原生的集羣化方案,而是使用基於Proxy的集羣化方案,業界比較知名開源 Proxy 有 Twemproxy 和 Codis [5],本文簡要介紹下 Codis,實際上不少知名大廠的 Proxy 都來源於Codis。

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

Codis 引入了Group的概念,每一個Group包括 1 個 Redis Master 及至少1個 Redis Slave,能夠認爲每一個Group是一個系統分片(Shard),與 Redis-cluster 同樣,Codis 也採用預分片的機制,整個集羣分紅 1024 個 slots,經過一致性哈希算法,將Key映射到某個 slot,再經過維護在 Zookeeper 裏的分片路由表,將Key的請求轉發到對應的Group上。

Codis 提供了一套運營監控界面,運維人員可經過 Dashboard 「自助式」地進行主從切換。

而對於應用而言,訪問 codis 和訪問原生的 Redis 並無任何區別,節點的動態上下線,slot 分配的變動都在 Proxy 層完美的對應用屏蔽了。

KV-DB

前文講述了 Mysql 和 Redis,或許對於大多數公司,這兩類存儲已經足夠。前者用於保存業務數據,後者用於集中式緩存。

可是對於大廠,還有若干場景上面兩種存儲沒法知足:例如推薦系統在線預測場景,須要將用戶畫像、商品畫像、商家畫像、用戶商戶交叉畫像在線加載預測上下文,特徵處理後給到模型作預測打分。ToC的互聯網產品的註冊用戶極可能過億,因此用戶畫像總存儲極可能百G甚至T。

若是是這樣規模的數據,Mysql的讀性能確定扛不住在線預測場景;Redis 是內存緩存,存儲昂貴,同時在容災恢復時候,Redis須要將AOF或者RDB數據載入內存後才能提供服務,數據量過大須要很長的恢復時間。因此須要另一種存儲能解決這個問題。

幾乎全部大廠都有屬於本身的KV-DB,例如360開源的Pika,餓了麼經過購買Tikv封裝而成Ekv,字節跳動的 Abase。

Pika 和 Tikv在存儲底層都使用了RocksDB做爲數據存儲,而RocksDB它是將數據存儲在硬盤上的,Pika 和Tikv在上層構建的都是集羣化方案,主從模式等,基於內存的一致性Cache等。下圖是Pika架構圖:

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

消息隊列(MQ)

伴隨着業務的複雜,咱們每每會遇到這個場景,一個數據操做後,須要觸發下游若干個子操做。例如外賣場景,用戶下訂單成功,要通知商家用戶訂單,要物流平臺對訂單進行調度和派單,要觸發一些後置的風控邏輯對訂單合法性進行校驗等。

若是是同步的設計,須要在訂單完成後對後續的操做一一進行API調用,這樣的作法讓訂單流程依賴更多外部服務,提高了業務複雜度,下降了服務的穩定性,因此咱們須要消息中間件來解耦操做。依賴的服務依賴下單消息,而不是在下單結束後,經過接口調用的方式觸發。

咱們能夠把消息隊列(MQ)比做是一個存放消息的容器,Producer 負責生產消息,將消息發送到MQ,Consumer取出消息供本身使用。如圖所示:

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

消息隊列是分佈式系統中重要的組件,使用消息隊列主要是爲了經過異步處理下降系統耦合性,除此以外,還能夠依賴消息隊列提升系統性能和削峯填谷。

關於削峯填谷這裏我舉一個應用場景 —— 搶購。

搶購是不少網站促銷的重要場景,呈現方式每每是經過倒計時的方式,在某個固定時間放出限量的優惠產品。

開放時間到來時,會有大量用戶觸發購買動做,咱們知道下訂單每每是一個耗時比較久的操做,須要對庫存,營銷信息,用戶等多方面數據作查詢、校驗、計算操做,同時爲了控制超賣,可能會引入鎖機制。若是處理很差搶購的瞬時流量,可能會打垮系統。

一種優化思路是能夠將瞬間的購買請求轉發到消息隊列中,再由消息隊列的消費者消費消息,進行後續的訂單操做,從而對系統進行流量削峯。

從大的應用場景上,咱們能夠將消息隊列的應用拆分紅兩類,一類是業務場景,例如上文提到查到用戶訂單消息,這類場景的吞吐量未必很大,可是須要消息中間件具備一些更高級的易於業務使用的特性,例如支持消息持久化,延遲消息等。

另一類是大數據場景,該類場景對吞吐量有極高的訴求,例如用戶行爲蒐集(User Behavior Tracking)等。這裏只介紹兩種上面場景適合的消息隊列中間件。

RocketMQ

RocketMQ是一款分佈式、隊列模型的消息中間件,是由阿里巴巴設計的,通過屢次雙十一流量洪峯的洗禮,讓它更有光環效應;RocketMQ是純java編寫,基於通訊框架Netty這也讓它擁有更好的社區基礎和可改造的空間。相比於Kafka,RocketMQ支持不少業務友好的特性,具備如下特色:

支持嚴格的消息順序,支持Topic與Queue兩種模式,億級消息堆積能力,比較友好的分佈式特性,同時支持Push與Pull方式消費消息

Kafka

Kafka 的特色其實很明顯,就是僅僅提供較少的核心功能,可是提供超高的吞吐量,毫秒級的延遲,極高的可用性以及可靠性,並且分佈式能夠任意擴展。同時 kafka 最好是支撐較少的 topic 數量便可,保證其超高吞吐量。

kafka 惟一的一點劣勢是有可能消息重複消費,那麼對數據準確性會形成極其輕微的影響,在大數據領域中以及日誌採集中,這點輕微影響能夠忽略。

對象存儲

對象存儲是面向對象/文件的、海量的互聯網存儲,它也能夠直接被稱爲「雲存儲」。對象儘管是文件,它是已被封裝的文件,也就是說,在對象存儲系統裏,你不能直接打開/修改文件,但能夠像ftp同樣上傳文件,下載文件等。

另外對象存儲沒有像文件系統那樣有一個不少層級的文件結構,而是隻有一個「桶」(bucket)的概念(也就是存儲空間),「桶」裏面所有都是對象,是一種很是扁平化的存儲方式。其最大的特色就是它的對象名稱就是一個域名地址,一旦對象被設置爲「公開」,全部網民均可以訪問到它;它的擁有者還能夠經過REST API的方式訪問其中的對象。

所以,對象存儲最主流的使用場景,就是存儲網站、移動app等互聯網/移動互聯網應用的靜態內容(視頻、圖片、文件、軟件安裝包等)

不過自建對象存儲成本很高,不少中等規模的廠,都會選擇商業化對象存儲方案,例如七牛雲,阿里OSS等,用來下降研發和維護成本。

Elastic Search

不管是在線應用仍是管理後臺,都有模糊搜索的需求,例如用戶搜索感興趣的帖子,評論,視頻。管理員對命中一些關鍵詞的內容進行批量下架等處理。

這種模糊搜索,若是使用Mysql原生的查詢,效率是很是低的,能想到的樸素作法可能先將用戶Query進行分詞處理,而後用分詞的結果依次提交到Mysql作某字段的Contains條件查詢。Contains操做會對錶進行全掃描,若是有千萬數據,效率不可思議。

針對這樣的場景,倒排索引是很是理想的方案,倒排索引(Inverted Index)是實現「單詞-文檔矩陣」的一種具體存儲形式,經過倒排索引,能夠根據單詞快速獲取包含這個單詞的文檔列表。

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

若是須要索引的數據很少,索引更新頻率也不高,簡單的作法可使用 Apache Lucene 構建一個很是輕量的倒排索引,將須要倒排的數據,經過 Lucene 提供的API 灌到索引文件中,而該索引文件能夠在後續的搜索服務中被 Lucene 加載,提供查詢服務。

可是大廠場景每每是擁有海量須要索引的數據,同時要支持在線構建索引文件和災備能力,在開源社區中 Elastic Search 就是很是好的選擇之一,ES 底層也是基於 Lucene,可是它提供分佈式的文檔存儲引擎,分佈式的搜索引擎和分析引擎,支持PB級數據。

除此以外,還有其它技術,例如容器、分佈式等等。

<END>

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

相關文章
相關標籤/搜索