sonic——可替代Elasticsearch的簡(jiǎn)單搜索引擎

簡(jiǎn)介

近期,筆者在github上發(fā)現(xiàn)了一個(gè)十分好玩的開源項(xiàng)目——sonic。sonic項(xiàng)目的介紹十分簡(jiǎn)單。

?? Fast, lightweight & schema-less search backend. An alternative to Elasticsearch that runs on a few MBs of RAM.

在這段話中,我們可以很迅速的了解sonic的特性。

首先,它很快,比Elasticsearch還要快很多,在官方給出的benchmark中,它的搜索都在毫秒級(jí)別的。

第二,它輕量,Elasticsearch在漫長的發(fā)展過程中,已經(jīng)變得越來越沉了,不僅支持搜索,存儲(chǔ),分析,可視化,Elasticsearch還擁抱上了大數(shù)據(jù),使Elasticsearch的學(xué)習(xí)曲線很高,而且使用成本也很高,普通的機(jī)器已經(jīng)完全不夠用了,而sonic十分的輕,上手快,API少,專注于搜索這一塊。

第三,無范式(schema-less)。請(qǐng)?jiān)徫疫@樣翻譯,Elasticsearch在使用中你需要先定義mappings來讓數(shù)據(jù)格式化。很多時(shí)候,定義固定結(jié)構(gòu)去存儲(chǔ)數(shù)據(jù)本應(yīng)該是數(shù)據(jù)庫該干的事,但是Elasticsearch支持了數(shù)據(jù)存儲(chǔ),因此你必須先完成這一步才能使用Elasticsearch。而sonic是無范式的,sonic不做數(shù)據(jù)的存儲(chǔ),它只做搜索,因此你不需要做mappings。

第四,省錢。在任何實(shí)際項(xiàng)目的開發(fā)和運(yùn)維中,成本大多時(shí)候被放在了第一位,sonic對(duì)于運(yùn)行機(jī)的要求很低,且內(nèi)存占用少,可以為你省下一大筆的開支。

說了這么多,你是否也想嘗試一下sonic?接下來我們一起來實(shí)操一下,看看能否窺一斑而知全豹

使用

安裝

首先一點(diǎn),sonic不支持windows,因此最好的使用方式便是docker,所以請(qǐng)先確保你會(huì)簡(jiǎn)單的使用docker,僅僅需要知道一些概念即可。

請(qǐng)?jiān)诮K端鍵入如下命令:

docker pull valeriansaliou/sonic:v1.2.0

等待一會(huì)兒,docker會(huì)幫我們搞定一切,拉取完成之后,我們需要一份簡(jiǎn)單的sonic配置文件——config.cfg。配置文件內(nèi)容如下:

# Sonic
# Fast, lightweight and schema-less search backend
# Configuration file
# Example: https://github.com/valeriansaliou/sonic/blob/master/config.cfg


[server]

log_level = "debug"


[channel]

inet = "0.0.0.0:1491"
tcp_timeout = 300

auth_password = "SecretPassword"

[channel.search]

query_limit_default = 10
query_limit_maximum = 100
query_alternates_try = 4

suggest_limit_default = 5
suggest_limit_maximum = 20


[store]

[store.kv]

path = "/var/lib/sonic/store/kv/"

retain_word_objects = 1000

[store.kv.pool]

inactive_after = 1800

[store.kv.database]

flush_after = 900

compress = true
parallelism = 2
max_files = 100
max_compactions = 1
max_flushes = 1
write_buffer = 16384
write_ahead_log = true

[store.fst]

path = "/var/lib/sonic/store/fst/"

[store.fst.pool]

inactive_after = 300

[store.fst.graph]

consolidate_after = 180

在這份配置文件中,你可能只需要注意兩個(gè)點(diǎn):

  • inet,sonic的監(jiān)聽端口,這里默認(rèn)為"0.0.0.0:1491"。
  • auth_password,sonic的密碼,這里默認(rèn)為"SecretPassword"

sonic在通信協(xié)議上選擇了更加高效的tcp協(xié)議,并且衍生了自己的一套腳本語言,放心僅僅只是幾句簡(jiǎn)單的查詢操作語句。

請(qǐng)將配置文件存放在一個(gè)合適的位置存儲(chǔ),如筆者的存儲(chǔ)位置在/Users/pedro/Desktop/sonic-test/config.cfg。

在終端輸入如下命令,我們開啟一個(gè)sonic服務(wù):

docker run -p 1491:1491 -v ~/Desktop/sonic-test/config.cfg:/etc/sonic.cfg  valeriansaliou/sonic:v1.2.0

等待一會(huì)兒,如果終端出現(xiàn)如下信息,則代表運(yùn)行成功:

(INFO) - starting up
(INFO) - started
(DEBUG) - spawn managed thread: tasker
(DEBUG) - spawn managed thread: channel
(INFO) - tasker is now active
(INFO) - listening on tcp://0.0.0.0:1491

概念

在具體的數(shù)據(jù)操作之前,我們十分有必要的去了解一下sonic的工作機(jī)制。請(qǐng)記住,這很重要,了解它你才會(huì)有足夠清晰的大局觀,才有可能做到窺一斑而知全豹。

sonic的操作可分為三個(gè)模式:

  • Search mode(搜索模式),sonic的模式區(qū)分很是硬核,在搜索模式下,你只能進(jìn)行搜索相關(guān)的操作,不能進(jìn)行數(shù)據(jù)插入和備份的相關(guān)操作。核心的有QUERYSUGGEST兩個(gè)操作,分別用來對(duì)進(jìn)行搜索和對(duì)進(jìn)行補(bǔ)全。
  • Ingest mode(插入模式),請(qǐng)記住sonic只有在插入模式下才能進(jìn)行數(shù)據(jù)的插入。sonic的數(shù)據(jù)插入核心的有三個(gè)操作,分別是PUSH、POPFLUSH。push會(huì)向存儲(chǔ)區(qū)中添加一個(gè)元素,pop則是從存儲(chǔ)區(qū)中彈出這個(gè)元素,flush則會(huì)將存儲(chǔ)區(qū)中的元素全部清除。
  • Control mode(控制模式),sonic可以在控制模式下,對(duì)數(shù)據(jù)進(jìn)行鞏固,備份和恢復(fù)等一系列的操作。核心的操作有TRIGGERINFO,trigger主要對(duì)數(shù)據(jù)進(jìn)行鞏固,備份和恢復(fù),而info用于查看sonic的運(yùn)行狀態(tài)。

在剛才我們談到過了sonic的協(xié)議,我們把它稱作Sonic Channel protocol。這份協(xié)議構(gòu)建在tcp的協(xié)議之上,如果你熟悉redis的話,你可能會(huì)發(fā)現(xiàn),二者很是相似。

sonic在此協(xié)議上衍生了這三大模式以及相關(guān)的操作,不難發(fā)現(xiàn),sonic的核心概念和使用真的十分簡(jiǎn)單,當(dāng)然了筆者不可能在此處全盤拖出,在sonic的文檔中詳細(xì)的給出了Sonic Channel protocol的具體細(xì)節(jié)和實(shí)用方法,如果感興趣,請(qǐng)務(wù)必了解一下。

操作

sonic的服務(wù)運(yùn)行起來以后,我們通過telnet這個(gè)實(shí)用的工具來操作一下它。

在終端輸入:

telnet localhost 1491

出現(xiàn)如下信息表示你連接成功。

Trying ::1...
Connected to localhost.
Escape character is '^]'.
CONNECTED <sonic-server v1.2.0>

在真正的插入之前,我們還需要對(duì)sonic的存儲(chǔ)做一下簡(jiǎn)單的概述。在文章的開頭,筆者說到sonic只關(guān)注于搜索,而將數(shù)據(jù)的存儲(chǔ)交給了其它的數(shù)據(jù)庫去實(shí)現(xiàn)。那么sonic真的不需要存儲(chǔ)嗎?

答案顯而易見,需要!難道這是欺騙嗎?當(dāng)然不是,sonic不做數(shù)據(jù)的存儲(chǔ),但它需要對(duì)搜索的部分?jǐn)?shù)據(jù)做索引和存儲(chǔ)。你可能會(huì)覺得有些繞,沒關(guān)系,我們舉個(gè)例子。

一篇文章,可能有標(biāo)題,綜述,正文,作者...等一系列的數(shù)據(jù)。那么在搜索這篇文章的時(shí)候,我們不可能搜索這所有的字段數(shù)據(jù),我們往往會(huì)采取一種折中的方式,搜索某幾個(gè)字段的數(shù)據(jù)。例如:我們搜索綜述和標(biāo)題,而放棄搜索龐大的正文數(shù)據(jù),這既提高了搜索效率,也降低了搜索成本。

這個(gè)時(shí)候,你再來理解,sonic它確實(shí)不做存儲(chǔ),它不會(huì)存儲(chǔ)這篇文章的所有字段,即不會(huì)存儲(chǔ)標(biāo)題,綜述,正文,作者等等,但是它需要存儲(chǔ)它用來做搜索的部分?jǐn)?shù)據(jù),即綜述和標(biāo)題。相比存儲(chǔ)所有字段的龐大數(shù)據(jù),綜述和標(biāo)題僅僅占了很小的一部分。

好,重點(diǎn)來了!sonic如何存儲(chǔ)這些有效的搜索數(shù)據(jù)的呢?sonic有兩個(gè)存儲(chǔ)點(diǎn),一個(gè)是kv存儲(chǔ),一個(gè)是fst存儲(chǔ)。kv存儲(chǔ)很好理解,即key-value存儲(chǔ),我們需要把綜述和標(biāo)題合并成一個(gè)value,并為它取上唯一的key,這個(gè)key一般對(duì)應(yīng)數(shù)據(jù)庫的主鍵,sonic會(huì)把這兩個(gè)值存儲(chǔ)到kv區(qū)。

對(duì)于把綜述和標(biāo)題合并成一個(gè)value,我想很多人會(huì)有些許不理解,把它們合并了還怎么搜索了?不用怕,sonic會(huì)自動(dòng)幫我們做分詞,并將其通過倒排索引的方式存儲(chǔ)起來,當(dāng)你在通過詞搜索的時(shí)候,一般情況下只會(huì)取幾個(gè)詞做搜索,而不會(huì)取全部,所以即使合并起來,影響也不大,當(dāng)然你也可以僅選擇一個(gè)字段做value,這樣就不會(huì)有合并的問題。

好,上段之中,我們拋出了倒排索引這個(gè)概念,在此處筆者對(duì)其不做詳細(xì)解釋,如果你想了解,查詢一些資料即可。你可以簡(jiǎn)單理解為倒排就是通過來找句子,索引會(huì)存儲(chǔ)句子之間的關(guān)聯(lián),然后通過搜索傳來的詞來反向?qū)ふ揖渥?。此處你可能已?jīng)意識(shí)到了,這些索引是不是要存儲(chǔ)到fst區(qū)啊。是的,這些倒排索引會(huì)存儲(chǔ)到fst區(qū),與kv區(qū)良好的分開。

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

好了,談了這么多,我們終于可以進(jìn)入到實(shí)操環(huán)節(jié)了。通過telnet連接sonic之后,我們嘗試插入一條數(shù)據(jù)。

telnet localhost 1491
Trying ::1...
Connected to localhost.
Escape character is '^]'.
CONNECTED <sonic-server v1.2.0>

# 此處以 START 開始 ingest模式 SecretPassword 是密碼,務(wù)必輸入密碼
START ingest SecretPassword
# sonic的返回信息
STARTED ingest protocol(1) buffer(20000)
# 通過PUSH 插入數(shù)據(jù)
# movie 為 collection名
# douban 為 bucket 名
# 1 為 object 名 即 key 值
# "the knight" 為 value 值
PUSH movie douban 1 "the knight"
# 插入成功后的返回值 ok
OK
# 退出
QUIT
ENDED quit

筆者已經(jīng)在注釋中,詳細(xì)的解釋了每一行命令的作用,但這可能還是不夠友好。sonic每次連接都可以被理解成一次會(huì)話(session),這個(gè)會(huì)話從START命令開始,當(dāng)然如果通過telnet連接后一段時(shí)間未執(zhí)行start,sonic會(huì)自動(dòng)關(guān)閉掉這個(gè)連接。

START命令后,會(huì)開始一個(gè)會(huì)話。具體的命令格式為START <mode> <password>,如START ingest SecretPassword會(huì)開啟插入模式(ingest model),密碼為SecretPassword。sonic鑒權(quán)成功后,返回會(huì)話建立成功的信息STARTED ingest protocol(1) buffer(20000)。

隨后,再通過PUSH命令插入一條數(shù)據(jù),命令格式為PUSH <collection> <bucket> <object> "<text>"。這里注意:sonic與大多數(shù)數(shù)據(jù)庫一樣都有層級(jí)的概念,如在mongodb中有 數(shù)據(jù)庫 -> 集合 -> 項(xiàng) -> 字段的層級(jí)概念,sonic也有 collection -> bucket -> [object:text]的層次。

當(dāng)然有人會(huì)問,這有啥用?。烤偷@條語句PUSH movie douban 1 "the knight"而言,它就可以看到層級(jí)的作用,它可以將搜索數(shù)據(jù)分類,更為重要的是,the knight歸到了movie集合下的douban桶,而當(dāng)有其它的集合時(shí),如song,我們可以有效的在某個(gè)集合的某個(gè)桶下進(jìn)行有效的搜索。

插入成功后,返回一個(gè)OK。

搜索數(shù)據(jù)

插入數(shù)據(jù)后,我們嘗試再次連接,并用搜索模式進(jìn)入一個(gè)會(huì)話。

# 開始一個(gè)搜索會(huì)話
START search SecretPassword
STARTED search protocol(1) buffer(20000)
# 搜索 movie -> douban 下的數(shù)據(jù),搜索關(guān)鍵字為 the
QUERY movie douban "the"
PENDING Q5Z3lY25
# 得到搜索結(jié)果,返回object,即key值 1
EVENT QUERY Q5Z3lY25 1

搜索作為sonic的最最最重要的部分,使用起來極其簡(jiǎn)單,但卻十分強(qiáng)大。其命令格式為QUERY <collection> <bucket> "<terms>" [LIMIT(<count>)]? [OFFSET(<count>)]?,熟悉sql的立馬就能理解如何使用了,collection和bucket表示詳細(xì)的層級(jí)關(guān)系,terms表示搜索的關(guān)鍵詞,limit 限制返回結(jié)果的數(shù)量,offset表示結(jié)果的偏移量。

PENDING Q5Z3lY25
EVENT QUERY Q5Z3lY25 1

這兩行均是搜索之后,sonic的返回信息,表示發(fā)生了一個(gè)事件,事件id為Q5Z3lY25,得到的結(jié)果是1。

sonic還支持單詞的自動(dòng)補(bǔ)全,如輸入th,它會(huì)返回the這個(gè)單詞,幫助你的搜索進(jìn)行自動(dòng)補(bǔ)全,提高用戶體驗(yàn)。具體的格式是:SUGGEST <collection> <bucket> "<word>" [LIMIT(<count>)]?。

START search SecretPassword
STARTED search protocol(1) buffer(20000)
# 輸入 th 這兩次字母
SUGGEST movie douban "th"
PENDING SukqsbYk
# 返回 the 這個(gè)已經(jīng)補(bǔ)全的單詞
EVENT SUGGEST SukqsbYk the

這里要注意一下,SUGGEST僅僅支持limit這一個(gè)項(xiàng),在書寫命令的時(shí)候請(qǐng)一定保持大寫即LIMIT。

其它

sonic在控制模式下,可以對(duì)數(shù)據(jù)進(jìn)行consolidate加固,backup備份,restore恢復(fù),以及INFO查看sonic服務(wù)的數(shù)據(jù)等操作。

這些操作對(duì)于數(shù)據(jù)維護(hù)以及服務(wù)運(yùn)維來說很重要,但顯然不是這篇文章的重點(diǎn)。以上的全部操作,均可以在sonic的文檔中找到,如果你感興趣,請(qǐng)務(wù)必閱讀一下,它真的很少,很方便上手。

結(jié)語

在文章開頭到結(jié)尾,筆者介紹了sonic的特性和它的一些概念,以及部分的工作原理。如果你單純的想要去使用sonic,那么請(qǐng)記住,熟悉本文提到的概念,保證對(duì)sonic的大局觀的理解,詳細(xì)閱讀一下它的文檔,那么你就可以去嘗試使用sonic。

到此,我們幾乎介紹到了sonic的全部,相較于Elasticsearch,它真的足夠小巧,足夠簡(jiǎn)單,將搜索做到了精細(xì)極致。

在下篇文章中,筆者會(huì)使用python,mongodb做一個(gè)簡(jiǎn)單的搜索應(yīng)用,盡情期待吧,諸君。

過度封裝帶來的簡(jiǎn)單性,并不會(huì)帶來真正的簡(jiǎn)單,只會(huì)帶來更加的復(fù)雜?!獊碜詓onic和Elasticsearch的對(duì)比思考

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容