簡介
近期,筆者在github上發(fā)現(xiàn)了一個十分好玩的開源項目——sonic
。sonic項目的介紹十分簡單媳危。
?? Fast, lightweight & schema-less search backend. An alternative to Elasticsearch that runs on a few MBs of RAM.
在這段話中,我們可以很迅速的了解sonic的特性。
首先既荚,它很快,比Elasticsearch還要快很多栋艳,在官方給出的benchmark中恰聘,它的搜索都在毫秒級別的。
第二吸占,它輕量晴叨,Elasticsearch在漫長的發(fā)展過程中,已經(jīng)變得越來越沉了矾屯,不僅支持搜索兼蕊,存儲,分析件蚕,可視化孙技,Elasticsearch還擁抱上了大數(shù)據(jù),使Elasticsearch的學習曲線很高排作,而且使用成本也很高牵啦,普通的機器已經(jīng)完全不夠用了,而sonic十分的輕妄痪,上手快哈雏,API少,專注于搜索這一塊衫生。
第三裳瘪,無范式(schema-less)。請原諒我這樣翻譯罪针,Elasticsearch在使用中你需要先定義mappings來讓數(shù)據(jù)格式化彭羹。很多時候,定義固定結(jié)構(gòu)去存儲數(shù)據(jù)本應該是數(shù)據(jù)庫該干的事站故,但是Elasticsearch支持了數(shù)據(jù)存儲皆怕,因此你必須先完成這一步才能使用Elasticsearch毅舆。而sonic是無范式的,sonic不做數(shù)據(jù)的存儲愈腾,它只做搜索憋活,因此你不需要做mappings。
第四虱黄,省錢悦即。在任何實際項目的開發(fā)和運維中,成本大多時候被放在了第一位橱乱,sonic對于運行機的要求很低辜梳,且內(nèi)存占用少,可以為你省下一大筆的開支泳叠。
說了這么多作瞄,你是否也想嘗試一下sonic
?接下來我們一起來實操一下危纫,看看能否窺一斑而知全豹
宗挥。
使用
安裝
首先一點,sonic不支持windows种蝶,因此最好的使用方式便是docker
契耿,所以請先確保你會簡單的使用docker,僅僅需要知道一些概念即可螃征。
請在終端鍵入如下命令:
docker pull valeriansaliou/sonic:v1.2.0
等待一會兒搪桂,docker會幫我們搞定一切,拉取完成之后盯滚,我們需要一份簡單的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
在這份配置文件中,你可能只需要注意兩個點:
- inet魄藕,sonic的監(jiān)聽端口裸燎,這里默認為
"0.0.0.0:1491"
。 - auth_password泼疑,sonic的密碼,這里默認為
"SecretPassword"
荷荤。
sonic在通信協(xié)議上選擇了更加高效的tcp協(xié)議退渗,并且衍生了自己的一套腳本語言,放心僅僅只是幾句簡單的查詢操作語句蕴纳。
請將配置文件存放在一個合適的位置存儲会油,如筆者的存儲位置在/Users/pedro/Desktop/sonic-test/config.cfg
。
在終端輸入如下命令古毛,我們開啟一個sonic服務:
docker run -p 1491:1491 -v ~/Desktop/sonic-test/config.cfg:/etc/sonic.cfg valeriansaliou/sonic:v1.2.0
等待一會兒翻翩,如果終端出現(xià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的工作機制嫂冻。請記住胶征,這很重要,了解它你才會有足夠清晰的大局觀桨仿,才有可能做到窺一斑而知全豹
睛低。
sonic的操作可分為三個模式:
- Search mode(搜索模式),sonic的模式區(qū)分很是硬核服傍,在搜索模式下钱雷,你只能進行搜索相關的操作,不能進行數(shù)據(jù)插入和備份的相關操作吹零。核心的有
QUERY
和SUGGEST
兩個操作罩抗,分別用來對詞
進行搜索和對字
進行補全。 - Ingest mode(插入模式)灿椅,請記住
sonic只有在插入模式下才能進行數(shù)據(jù)的插入
套蒂。sonic的數(shù)據(jù)插入核心的有三個操作,分別是PUSH
阱扬、POP
和FLUSH
泣懊。push會向存儲區(qū)中添加一個元素,pop則是從存儲區(qū)中彈出這個元素麻惶,flush則會將存儲區(qū)中的元素全部清除馍刮。 - Control mode(控制模式),sonic可以在控制模式下窃蹋,對數(shù)據(jù)進行鞏固卡啰,備份和恢復等一系列的操作。核心的操作有
TRIGGER
和INFO
警没,trigger主要對數(shù)據(jù)進行鞏固匈辱,備份和恢復,而info用于查看sonic的運行狀態(tài)杀迹。
在剛才我們談到過了sonic的協(xié)議亡脸,我們把它稱作Sonic Channel protocol
。這份協(xié)議構(gòu)建在tcp的協(xié)議之上树酪,如果你熟悉redis的話浅碾,你可能會發(fā)現(xiàn),二者很是相似续语。
sonic在此協(xié)議上衍生了這三大模式以及相關的操作垂谢,不難發(fā)現(xiàn),sonic的核心概念和使用真的十分簡單疮茄,當然了筆者不可能在此處全盤拖出滥朱,在sonic的文檔中詳細的給出了Sonic Channel protocol
的具體細節(jié)和實用方法根暑,如果感興趣,請務必了解一下徙邻。
操作
sonic的服務運行起來以后排嫌,我們通過telnet
這個實用的工具來操作一下它。
在終端輸入:
telnet localhost 1491
出現(xiàn)如下信息表示你連接成功鹃栽。
Trying ::1...
Connected to localhost.
Escape character is '^]'.
CONNECTED <sonic-server v1.2.0>
在真正的插入之前躏率,我們還需要對sonic的存儲
做一下簡單的概述。在文章的開頭民鼓,筆者說到sonic只關注于搜索薇芝,而將數(shù)據(jù)的存儲交給了其它的數(shù)據(jù)庫去實現(xiàn)。那么sonic真的不需要存儲嗎丰嘉?
答案顯而易見夯到,需要!難道這是欺騙嗎饮亏?當然不是耍贾,sonic不做數(shù)據(jù)的存儲,但它需要對搜索的部分數(shù)據(jù)做索引和存儲路幸。你可能會覺得有些繞荐开,沒關系,我們舉個例子简肴。
一篇文章晃听,可能有標題,綜述砰识,正文能扒,作者...等一系列的數(shù)據(jù)。那么在搜索這篇文章的時候辫狼,我們不可能搜索這所有的字段數(shù)據(jù)初斑,我們往往會采取一種折中的方式,搜索某幾個字段的數(shù)據(jù)膨处。例如:我們搜索綜述和標題见秤,而放棄搜索龐大的正文數(shù)據(jù),這既提高了搜索效率真椿,也降低了搜索成本秦叛。
這個時候,你再來理解瀑粥,sonic它確實不做存儲,它不會存儲這篇文章的所有字段三圆,即不會存儲標題狞换,綜述避咆,正文,作者等等修噪,但是它需要存儲它用來做搜索的部分數(shù)據(jù)查库,即綜述和標題。相比存儲所有字段的龐大數(shù)據(jù)黄琼,綜述和標題僅僅占了很小的一部分樊销。
好,重點來了脏款!sonic如何存儲這些有效的搜索數(shù)據(jù)的呢围苫?sonic有兩個存儲點,一個是kv
存儲撤师,一個是fst
存儲剂府。kv
存儲很好理解,即key-value
存儲剃盾,我們需要把綜述和標題合并成一個value
腺占,并為它取上唯一的key
,這個key
一般對應數(shù)據(jù)庫的主鍵痒谴,sonic會把這兩個值存儲到kv
區(qū)衰伯。
對于把綜述和標題合并成一個value
,我想很多人會有些許不理解积蔚,把它們合并了還怎么搜索了意鲸?不用怕,sonic會自動幫我們做分詞库倘,并將其通過倒排索引
的方式存儲起來临扮,當你在通過詞搜索的時候,一般情況下只會取幾個詞做搜索教翩,而不會取全部杆勇,所以即使合并起來,影響也不大饱亿,當然你也可以僅選擇一個字段做value
蚜退,這樣就不會有合并的問題。
好彪笼,上段之中钻注,我們拋出了倒排索引
這個概念,在此處筆者對其不做詳細解釋配猫,如果你想了解幅恋,查詢一些資料即可。你可以簡單理解為倒排
就是通過詞
來找句子
泵肄,索引會存儲詞
和句子
之間的關聯(lián)捆交,然后通過搜索傳來的詞來反向?qū)ふ揖渥邮缫怼4颂幠憧赡芤呀?jīng)意識到了,這些索引是不是要存儲到fst
區(qū)啊品追。是的玄括,這些倒排索引會存儲到fst
區(qū),與kv
區(qū)良好的分開肉瓦。
插入數(shù)據(jù)
好了遭京,談了這么多,我們終于可以進入到實操環(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 是密碼戒财,務必輸入密碼
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)在注釋中热监,詳細的解釋了每一行命令的作用,但這可能還是不夠友好饮寞。sonic每次連接都可以被理解成一次會話(session)孝扛,這個會話從START
命令開始,當然如果通過telnet連接后一段時間未執(zhí)行start幽崩,sonic會自動關閉掉這個連接苦始。
START
命令后,會開始一個會話慌申。具體的命令格式為START <mode> <password>
陌选,如START ingest SecretPassword
會開啟插入模式(ingest model),密碼為SecretPassword
蹄溉。sonic鑒權(quán)成功后咨油,返回會話建立成功的信息STARTED ingest protocol(1) buffer(20000)
。
隨后柒爵,再通過PUSH
命令插入一條數(shù)據(jù)役电,命令格式為PUSH <collection> <bucket> <object> "<text>"
。這里注意:sonic與大多數(shù)數(shù)據(jù)庫一樣都有層級
的概念棉胀,如在mongodb
中有 數(shù)據(jù)庫 -> 集合 -> 項 -> 字段的層級概念法瑟,sonic也有 collection -> bucket -> [object:text]的層次。
當然有人會問唁奢,這有啥用蚌?就但這條語句PUSH movie douban 1 "the knight"
而言麻掸,它就可以看到層級的作用酥夭,它可以將搜索數(shù)據(jù)分類,更為重要的是,the knight歸到了movie
集合下的douban
桶采郎,而當有其它的集合時千所,如song
,我們可以有效的在某個集合的某個桶下進行有效的搜索蒜埋。
插入成功后该贾,返回一個OK
别凤。
搜索數(shù)據(jù)
插入數(shù)據(jù)后杏节,我們嘗試再次連接须鼎,并用搜索模式進入一個會話低剔。
# 開始一個搜索會話
START search SecretPassword
STARTED search protocol(1) buffer(20000)
# 搜索 movie -> douban 下的數(shù)據(jù)亲善,搜索關鍵字為 the
QUERY movie douban "the"
PENDING Q5Z3lY25
# 得到搜索結(jié)果向臀,返回object工三,即key值 1
EVENT QUERY Q5Z3lY25 1
搜索作為sonic的最最最重要的部分犯建,使用起來極其簡單讲冠,但卻十分強大。其命令格式為QUERY <collection> <bucket> "<terms>" [LIMIT(<count>)]? [OFFSET(<count>)]?
适瓦,熟悉sql
的立馬就能理解如何使用了竿开,collection和bucket表示詳細的層級關系,terms表示搜索的關鍵詞玻熙,limit 限制返回結(jié)果的數(shù)量否彩,offset表示結(jié)果的偏移量。
PENDING Q5Z3lY25
EVENT QUERY Q5Z3lY25 1
這兩行均是搜索之后嗦随,sonic的返回信息列荔,表示發(fā)生了一個事件,事件id為Q5Z3lY25枚尼,得到的結(jié)果是1
贴浙。
sonic還支持單詞的自動補全,如輸入th
署恍,它會返回the
這個單詞崎溃,幫助你的搜索進行自動補全,提高用戶體驗锭汛。具體的格式是:SUGGEST <collection> <bucket> "<word>" [LIMIT(<count>)]?
笨奠。
START search SecretPassword
STARTED search protocol(1) buffer(20000)
# 輸入 th 這兩次字母
SUGGEST movie douban "th"
PENDING SukqsbYk
# 返回 the 這個已經(jīng)補全的單詞
EVENT SUGGEST SukqsbYk the
這里要注意一下,SUGGEST
僅僅支持limit這一個項唤殴,在書寫命令的時候請一定保持大寫即LIMIT
般婆。
其它
sonic在控制模式下,可以對數(shù)據(jù)進行consolidate
加固朵逝,backup
備份蔚袍,restore
恢復,以及INFO
查看sonic服務的數(shù)據(jù)等操作。
這些操作對于數(shù)據(jù)維護以及服務運維來說很重要啤咽,但顯然不是這篇文章的重點晋辆。以上的全部操作,均可以在sonic的文檔中找到宇整,如果你感興趣瓶佳,請務必閱讀一下,它真的很少鳞青,很方便上手霸饲。
結(jié)語
在文章開頭到結(jié)尾,筆者介紹了sonic的特性和它的一些概念臂拓,以及部分的工作原理厚脉。如果你單純的想要去使用sonic,那么請記住胶惰,熟悉本文提到的概念傻工,保證對sonic的大局觀的理解,詳細閱讀一下它的文檔孵滞,那么你就可以去嘗試使用sonic中捆。
到此,我們幾乎介紹到了sonic的全部剃斧,相較于Elasticsearch轨香,它真的足夠小巧,足夠簡單幼东,將搜索做到了精細極致臂容。
在下篇文章中,筆者會使用python
根蟹,mongodb
做一個簡單的搜索應用脓杉,盡情期待吧,諸君简逮。
過度封裝帶來的簡單性球散,并不會帶來真正的簡單,只會帶來更加的復雜散庶〗堆撸——來自sonic和Elasticsearch的對比思考