在文章正式開始前,大家打開 12306.cn 搜索一趟列車,根據搜索條件判斷,數據搜索技術使用 ElasticSearch 或者其它搜索技術是否合適?
這里我先把答案說下,12306 車票搜索用的是 Redis ,而不是大家常用的 ElasticSearch。至于為什么?大家可以先思考下再繼續閱讀。
12306 列車搜索條件
先來一張 12306 列車檢索的截圖,讓大家看下 12306 都有哪些搜索條件。
搜索條件如下:
- 單程或者往返
- 出發地
- 目的地
- 出發日或者返程日
- 普通或者學生
- 車次類型
- 出發車站
- 到達車站
- 車次席別
- 發車時間
- 顯示積分兌換車次
- 顯示全部可預訂車次
許多同學都感到疑惑,因為搜索條件實在太多了,這似乎會嚴重影響數據庫的性能。有些人甚至認為,如果性能不佳,至少應該使用 Elasticsearch 等搜索引擎來處理。這也是我一開始的想法,與大多數同學一致。
然而,隨著進一步的思考,我發現了一個有意思的頁面交互,這改變了我的看法。跟著馬哥的思路,一起來深入探討一下。
數據搜索框架
1. 搜索中間件 ElasticSearch
ElasticSearch 是一款非常強大的、基于 Lucene 的開源搜索及分析引擎;它是一個實時的分布式搜索分析引擎,它能讓你以前所未有的速度和規模,去探索你的數據。
許多年前,一個剛結婚的名叫 Shay Banon 的失業開發者,跟著他的妻子去了倫敦,他的妻子在那里學習廚師。 在尋找一個賺錢的工作的時候,為了給他的妻子做一個食譜搜索引擎,他開始使用 Lucene 的一個早期版本。
直接使用 Lucene 是很難的,因此 Shay 開始做一個抽象層,Java 開發者使用它可以很簡單的給他們的程序添加搜索功能。 他發布了他的第一個開源項目 Compass。
后來 Shay 獲得了一份工作,主要是高性能,分布式環境下的內存數據網格。這個對于高性能,實時,分布式搜索引擎的需求尤為突出, 他決定重寫 Compass,把它變為一個獨立的服務并取名 Elasticsearch。
第一個公開版本在2010年2月發布,從此以后,Elasticsearch 已經成為了 Github 上最活躍的項目之一,他擁有超過 300 名 contributors。 一家公司已經開始圍繞 Elasticsearch 提供商業服務,并開發新的特性,但是,Elasticsearch 將永遠開源并對所有人可用。
據說,Shay 的妻子還在等著她的食譜搜索引擎…
?
Elasticsearch 提供了一個強大而靈活的搜索和分析引擎,適用于各種應用場景,包括日志分析、電子商務搜索、實時監控等。它具有高性能、可擴展性和可用性,能夠處理大規模數據,并提供豐富的搜索、分析和可視化功能,幫助用戶從數據中獲取有價值的信息。
根據大家對 Elasticsearch 的了解,以及對 12306 復雜搜索條件的背景,肯定是 Elasticsearch 更適合實現改數據檢索的功能。不急,咱們繼續往下看。
2. 緩存中間件 Redis
Redis(Remote Dictionary Server)是一個開源的內存數據結構存儲系統,被廣泛應用于緩存、消息隊列、實時數據分析、排行榜等場景。它提供了以下主要功能:
- 內存緩存:Redis 將數據存儲在內存中,以實現高速的讀寫操作。作為緩存系統,它可以顯著提升應用程序的性能,減少對后端存儲系統的訪問壓力。
- 鍵值存儲:Redis 是一個鍵值存儲系統,其中的數據是以鍵值對的形式進行存儲和訪問。這使得 Redis 非常適合存儲簡單的數據結構,如字符串、哈希表、列表、集合和有序集合。
- 發布/訂閱:Redis 支持發布/訂閱模式,允許多個客戶端通過訂閱頻道來接收消息,同時可以通過發布消息來向訂閱者廣播消息。這使得 Redis 可以用作消息隊列、實時通知等場景。
- 數據持久化:Redis支持將內存中的數據持久化到硬盤中,以便在重啟后恢復數據。它提供了兩種持久化方式:RDB(Redis Database)快照和 AOF(Append-Only File)日志。
- 分布式:Redis 提供了一些分布式特性,如主從復制、集群等。主從復制可以實現數據的熱備份和讀寫分離,在主節點寫入數據后,數據會自動同步到從節點。集群模式可以將數據分布在多個節點上,提供更高的容量和吞吐量。
- 事務支持:Redis 支持事務操作,可以將一系列操作組合成一個原子操作進行提交。通過事務,可以確保多個操作在執行過程中不會被其他客戶端中斷。
- Lua 腳本:Redis 支持使用 Lua 腳本執行復雜的操作。通過編寫腳本,可以減少與 Redis 之間的網絡通信次數,提高性能。
大家對 Redis 熟知的一些概念就是 Redis 非常快,那快是如何體現以及原理是什么?
- 數據存儲在內存中: Redis 將數據存儲在內存中,這使得數據的讀取和寫入非常快。內存的隨機訪問速度遠遠快于磁盤上的存儲,因此 Redis 能夠在極短的時間內響應讀寫請求。
- 單線程模型: Redis 采用單線程模型,這意味著在任何給定時刻只有一個線程處理請求。盡管它是單線程的,但通過使用非阻塞I/O和事件循環,它能夠處理大量并發請求而不需要消耗大量的 CPU 開銷。這減少了上下文切換和鎖競爭,提高了性能。
- 精心優化的數據結構: Redis 支持多種數據結構,如字符串、哈希表、列表、集合、有序集合等,每種數據結構都經過高度優化,以提供高性能的操作。例如,Redis的有序集合允許你快速進行范圍查詢和排名操作。
- 高度優化的網絡協議: Redis 使用高度優化的協議進行與客戶端的通信,如 RESP(REdis Serialization Protocol)。這個協議非常輕量,減少了網絡通信的開銷,從而提高了性能。
為什么使用 Redis
考慮使用 Redis 和 Elasticsearch 兩個技術都是有一定道理的,它們分別有自己的優勢和適用場景。
作為承受請求最多的列車搜索功能,需要同時兼容實時性、并發性以及部署成本幾大要點。為此,我梳理了為什么必須用 Redis 的幾個原因。
1. 實時性能
- 內存存儲: Redis 將數據存儲在內存中,因此具有極低的讀取延遲,可以快速響應實時查詢請求。這對于需要即時更新的列車數據非常重要。
- 單線程模型: Redis 使用單線程模型,雖然是單線程的,但通過非阻塞 I/O 和事件循環,它可以處理大量并發請求,減少了上下文切換和鎖競爭,提高了實時性。
2. 并發性能
- 多客戶端支持: Redis 支持多個客戶端并發連接,每個客戶端可以獨立地執行讀取和寫入操作,這使得它在處理高并發請求時表現出色。
- 原子性操作: Redis 提供了原子性操作,如原子增減和原子加鎖,這些操作可以在多線程或多進程環境下安全使用,有助于處理并發操作。
3. 部署成本
- 輕量級: Redis 是一款輕量級的數據庫,易于部署和維護。它的內存占用相對較低,可以在相對較小的硬件配置上運行,從而減少了部署成本。
- 容易擴展: Redis 集群模式允許你將數據分布在多個節點上,以增加吞吐量和可伸縮性,而且這一擴展性是相對容易實現的。
公司實際用過 ElasticSearch 集群的同學應該知道,這玩意就是個性能深淵,非常消耗資源,懂得都懂。
4. 搜索條件拆解
到這里,許多人可能會有疑問,面對如此多的搜索條件,難道不應該使用 Elasticsearch 嗎?然而,這正是要強調為什么選擇 Redis 的關鍵原因。
您是否注意到了這張圖的一個關鍵點?它只允許選擇一天的出發日期。深思熟慮一下。
如果只能選擇一天,那我們是不是可以這么來設計 Redis 緩存存儲 12306 列車查詢數據。
也許有些人會問,這么多的查詢條件怎么處理呢?你可以親自在12306網站上嘗試,雖然頁面上有很多查詢條件,但大多數條件都是由前端進行篩選,實際上并沒有觸發后端的請求。
?
文末總結
12306列車數據搜索具有多個搜索條件,包括單程/往返、出發地、目的地、出發日期/返程日期、乘客類型、車次類型、出發車站、到達車站、車次席別、發車時間、顯示積分兌換車次以及顯示全部可預訂車次等。這些條件使搜索功能變得復雜,但在實際使用中,大部分條件是前端篩選,而不是每個條件都會發起后端請求。
在這種情況下,Redis作為列車數據的緩存存儲是有道理的,原因如下:
- 實時性: Redis 以內存為基礎,具有極低的讀取延遲,可以快速響應實時查詢請求,這對于需要即時更新的列車數據非常重要。單程或往返、出發日期等條件可以通過快速的 Redis 查詢來滿足。
- 緩存: Redis 是一個出色的緩存數據庫,可以用于緩存熱門的列車路線和查詢結果,從而減輕后端數據庫的負載。對于需要被查詢的路線,可以將其結果緩存在 Redis 中,以提高響應速度。
- 簡單性: Redis 的數據模型相對簡單,適合存儲簡單的鍵值對或一些常規數據結構。這使得 Redis 適合存儲一些搜索條件,如出發地、目的地、車次類型等,以便快速篩選結果。
- 部署成本: Redis 是一款輕量級的數據庫,易于部署和維護。它的內存占用相對較低,可以在相對較小的硬件配置上運行,從而減少了部署成本。
- 只需后端查詢一次: 在實際操作中,頁面上的搜索條件大多是前端篩選,而只有在點擊查詢按鈕時才會發起后端請求。因此,Redis 可以用于快速存儲和檢索列車數據,而 Elasticsearch 等搜索引擎可以在需要進行全文搜索或復雜查詢時使用。
總的來說,Redis 作為列車數據的緩存存儲在實時性、并發性和部署成本方面具有一些優勢,尤其適用于快速檢索和緩存常用路線數據。然而,對于復雜的全文搜索和高級查詢需求,可以考慮將 Redis 與 Elasticsearch 等搜索引擎結合使用,以充分發揮它們各自的優勢。