本發(fā)明涉及計(jì)算機(jī)網(wǎng)絡(luò)技術(shù)領(lǐng)域,具體涉及一種數(shù)據(jù)寫(xiě)請(qǐng)求處理方法、裝置及分布式數(shù)據(jù)存儲(chǔ)系統(tǒng)。
背景技術(shù):
在分布式數(shù)據(jù)存儲(chǔ)系統(tǒng)中,一般會(huì)利用分布式組件來(lái)將調(diào)用端發(fā)送的數(shù)據(jù)寫(xiě)請(qǐng)求轉(zhuǎn)發(fā)給存儲(chǔ)引擎,其中,分布式組件為反向代理服務(wù)器,具體地,可以為Nginx服務(wù)器。對(duì)于KV存儲(chǔ)來(lái)說(shuō),Nginx內(nèi)置的負(fù)載均衡的策略,無(wú)論是round-robin,還是ip_hash,還是url_hash,都不能實(shí)現(xiàn)根據(jù)key來(lái)進(jìn)行負(fù)載均衡的需求,舉例說(shuō)明,以分布式組件采用的是1Primary-1Replica Shard的存儲(chǔ)模式為例,這必然涉及到兩次寫(xiě)存儲(chǔ)的操作,而這兩次的寫(xiě)入需要是兩臺(tái)完全不同的節(jié)點(diǎn),但Nginx內(nèi)置的負(fù)載均衡策略無(wú)法滿足這樣高度定制化的需求,其根本原因在于,Nginx的負(fù)載均衡策略將存儲(chǔ)節(jié)點(diǎn)的地址等細(xì)節(jié)完全對(duì)外層屏蔽了,在編寫(xiě)http模塊時(shí)不可能通過(guò)任何一個(gè)內(nèi)置函數(shù)拿到某個(gè)存儲(chǔ)節(jié)點(diǎn)的地址,也就是說(shuō)這些細(xì)節(jié)對(duì)于開(kāi)發(fā)者是透明的,從而限制了定制化的負(fù)載均衡策略的實(shí)現(xiàn)。
技術(shù)實(shí)現(xiàn)要素:
鑒于上述問(wèn)題,提出了本發(fā)明以便提供一種克服上述問(wèn)題或者至少部分地解決上述問(wèn)題的數(shù)據(jù)寫(xiě)請(qǐng)求處理方法、數(shù)據(jù)寫(xiě)請(qǐng)求處理裝置和相應(yīng)的分布式數(shù)據(jù)存儲(chǔ)系統(tǒng)。
根據(jù)本發(fā)明的一個(gè)方面,提供了一種數(shù)據(jù)寫(xiě)請(qǐng)求處理方法,該方法基于調(diào)用端發(fā)送的數(shù)據(jù)寫(xiě)請(qǐng)求向存儲(chǔ)節(jié)點(diǎn)中寫(xiě)入數(shù)據(jù),其中數(shù)據(jù)寫(xiě)請(qǐng)求包含主請(qǐng)求和至少一個(gè)子請(qǐng)求,方法包括:
對(duì)于每一個(gè)子請(qǐng)求,調(diào)用訪問(wèn)接口從全局變量中選擇待寫(xiě)入數(shù)據(jù)的存儲(chǔ)節(jié)點(diǎn)的存儲(chǔ)節(jié)點(diǎn)地址,向存儲(chǔ)節(jié)點(diǎn)發(fā)送子請(qǐng)求,其中將選擇的存儲(chǔ)節(jié)點(diǎn)地址保存至子請(qǐng)求的上下文中;
從子請(qǐng)求的上下文中提取出所選擇的存儲(chǔ)節(jié)點(diǎn)地址,并保存至存儲(chǔ)節(jié)點(diǎn)的上下文中;
從存儲(chǔ)節(jié)點(diǎn)的上下文中提取出存儲(chǔ)節(jié)點(diǎn)地址,與存儲(chǔ)節(jié)點(diǎn)建立連接,將數(shù)據(jù)寫(xiě)入到相應(yīng)的存儲(chǔ)節(jié)點(diǎn)。
根據(jù)本發(fā)明的另一方面,提供了一種數(shù)據(jù)寫(xiě)請(qǐng)求處理裝置,該裝置基于調(diào)用端發(fā)送的數(shù)據(jù)寫(xiě)請(qǐng)求向存儲(chǔ)節(jié)點(diǎn)中寫(xiě)入數(shù)據(jù),其中數(shù)據(jù)寫(xiě)請(qǐng)求包含主請(qǐng)求和至少一個(gè)子請(qǐng)求,裝置包括:用于處理子請(qǐng)求的處理器;
用于處理子請(qǐng)求的處理器包括:
選擇單元,適于對(duì)于每一個(gè)子請(qǐng)求,調(diào)用訪問(wèn)接口從全局變量中選擇待寫(xiě)入數(shù)據(jù)的存儲(chǔ)節(jié)點(diǎn)的存儲(chǔ)節(jié)點(diǎn)地址;
子請(qǐng)求處理單元,適于向存儲(chǔ)節(jié)點(diǎn)發(fā)送子請(qǐng)求,其中將選擇的存儲(chǔ)節(jié)點(diǎn)地址保存至子請(qǐng)求的上下文中;
提取單元,適于從子請(qǐng)求的上下文中提取出所選擇的存儲(chǔ)節(jié)點(diǎn)地址;
上下文寫(xiě)入單元,適于將提取出的存儲(chǔ)節(jié)點(diǎn)地址保存至存儲(chǔ)節(jié)點(diǎn)的上下文中;
連接單元,適于從存儲(chǔ)節(jié)點(diǎn)的上下文中提取出存儲(chǔ)節(jié)點(diǎn)地址,與存儲(chǔ)節(jié)點(diǎn)建立連接;
數(shù)據(jù)寫(xiě)入單元,適于將數(shù)據(jù)寫(xiě)入到相應(yīng)的存儲(chǔ)節(jié)點(diǎn)。
根據(jù)本發(fā)明的另一方面,提供了一種分布式數(shù)據(jù)存儲(chǔ)系統(tǒng),包括:調(diào)用端、分布式組件和存儲(chǔ)節(jié)點(diǎn);其中,分布式組件包括上述數(shù)據(jù)寫(xiě)請(qǐng)求處理裝置。
根據(jù)本發(fā)明提供的方案,對(duì)于每一個(gè)子請(qǐng)求,調(diào)用訪問(wèn)接口從全局變量中選擇待寫(xiě)入數(shù)據(jù)的存儲(chǔ)節(jié)點(diǎn)的存儲(chǔ)節(jié)點(diǎn)地址,向存儲(chǔ)節(jié)點(diǎn)發(fā)送子請(qǐng)求,其中將選擇的存儲(chǔ)節(jié)點(diǎn)地址保存至子請(qǐng)求的上下文中,從子請(qǐng)求的上下文中提取出所選擇的存儲(chǔ)節(jié)點(diǎn)地址,并保存至存儲(chǔ)節(jié)點(diǎn)的上下文中,從存儲(chǔ)節(jié)點(diǎn)的上下文中提取出存儲(chǔ)節(jié)點(diǎn)地址,與存儲(chǔ)節(jié)點(diǎn)建立連接,將數(shù)據(jù)寫(xiě)入到相應(yīng)的存儲(chǔ)節(jié)點(diǎn)。在本發(fā)明方案中,利用全局變量記錄存儲(chǔ)節(jié)點(diǎn)的存儲(chǔ)節(jié)點(diǎn)地址,而且該全局變量提供有供訪問(wèn)的訪問(wèn)接口,通過(guò)調(diào)用該訪問(wèn)接口即可獲取待寫(xiě)入數(shù)據(jù)的存儲(chǔ)節(jié)點(diǎn)的存儲(chǔ)節(jié)點(diǎn)地址,使存儲(chǔ)節(jié)點(diǎn)地址暴露出來(lái),從而能夠滿足調(diào)用端的定制化要求向指定存儲(chǔ)節(jié)點(diǎn)寫(xiě)入數(shù)據(jù),實(shí)現(xiàn)了定制化的負(fù)載均衡,解決了KV存儲(chǔ)的單點(diǎn)限制。
上述說(shuō)明僅是本發(fā)明技術(shù)方案的概述,為了能夠更清楚了解本發(fā)明的技術(shù)手段,而可依照說(shuō)明書(shū)的內(nèi)容予以實(shí)施,并且為了讓本發(fā)明的上述和其它目的、特征和優(yōu)點(diǎn)能夠更明顯易懂,以下特舉本發(fā)明的具體實(shí)施方式。
附圖說(shuō)明
通過(guò)閱讀下文優(yōu)選實(shí)施方式的詳細(xì)描述,各種其他的優(yōu)點(diǎn)和益處對(duì)于本領(lǐng)域普通技術(shù)人員將變得清楚明了。附圖僅用于示出優(yōu)選實(shí)施方式的目的,而并不認(rèn)為是對(duì)本發(fā)明的限制。而且在整個(gè)附圖中,用相同的參考符號(hào)表示相同的部件。在附圖中:
圖1示出了根據(jù)本發(fā)明一個(gè)實(shí)施例的數(shù)據(jù)寫(xiě)請(qǐng)求處理方法的流程示意圖;
圖2示出了根據(jù)本發(fā)明另一個(gè)實(shí)施例的數(shù)據(jù)寫(xiě)請(qǐng)求處理方法的流程示意圖;
圖3示出了根據(jù)本發(fā)明一個(gè)實(shí)施例的數(shù)據(jù)寫(xiě)請(qǐng)求處理裝置的結(jié)構(gòu)示意圖;
圖4示出了根據(jù)本發(fā)明另一個(gè)實(shí)施例的數(shù)據(jù)寫(xiě)請(qǐng)求處理裝置的結(jié)構(gòu)示意圖;
圖5示出了根據(jù)本發(fā)明一個(gè)實(shí)施例的分布式數(shù)據(jù)存儲(chǔ)系統(tǒng)的結(jié)構(gòu)示意圖。
具體實(shí)施方式
下面將參照附圖更詳細(xì)地描述本公開(kāi)的示例性實(shí)施例。雖然附圖中顯示了本公開(kāi)的示例性實(shí)施例,然而應(yīng)當(dāng)理解,可以以各種形式實(shí)現(xiàn)本公開(kāi)而不應(yīng)被這里闡述的實(shí)施例所限制。相反,提供這些實(shí)施例是為了能夠更透徹地理解本公開(kāi),并且能夠?qū)⒈竟_(kāi)的范圍完整的傳達(dá)給本領(lǐng)域的技術(shù)人員。
本發(fā)明提出了一種數(shù)據(jù)寫(xiě)請(qǐng)求處理方法及裝置,適用于分布式數(shù)據(jù)存儲(chǔ)系統(tǒng),該系統(tǒng)包括:客戶端、Linux虛擬服務(wù)器集群(LVS)、分布式組件(HustDB HA,簡(jiǎn)稱HA)和存儲(chǔ)引擎(HustDB)。其中,分布式組件為反向代理服務(wù)器,具體可以是Nginx服務(wù)器??蛻舳撕蚅VS可作為調(diào)用端,例如,客戶端和LVS之間由于業(yè)務(wù)交互產(chǎn)生數(shù)據(jù),LVS發(fā)送數(shù)據(jù)寫(xiě)請(qǐng)求,期望將業(yè)務(wù)相關(guān)數(shù)據(jù)寫(xiě)入存儲(chǔ)節(jié)點(diǎn)中。另外,在一些特殊業(yè)務(wù)場(chǎng)景中,調(diào)用端可能為其它上層應(yīng)用或調(diào)用程序,例如,分布式組件內(nèi)部的調(diào)用程序。調(diào)用端具體與實(shí)際業(yè)務(wù)情況相關(guān)聯(lián),本發(fā)明對(duì)此不作限制。
在該分布式數(shù)據(jù)存儲(chǔ)系統(tǒng)中,將分布式組件與存儲(chǔ)引擎分離,存儲(chǔ)引擎只負(fù)責(zé)數(shù)據(jù)存儲(chǔ),以及對(duì)外提供http接口,以供分布式組件根據(jù)所提供的http接口向?qū)?yīng)的存儲(chǔ)節(jié)點(diǎn)寫(xiě)入數(shù)據(jù),其中,存儲(chǔ)引擎包括多個(gè)存儲(chǔ)節(jié)點(diǎn),各個(gè)存儲(chǔ)節(jié)點(diǎn)是相互獨(dú)立的,存儲(chǔ)節(jié)點(diǎn)彼此之間不會(huì)直接進(jìn)行通信,從而降低了存儲(chǔ)引擎的復(fù)雜度。
存儲(chǔ)節(jié)點(diǎn)可以為鍵值(Key-Value,以下簡(jiǎn)稱:KV)存儲(chǔ)數(shù)據(jù)庫(kù),這是一種NoSQL(非關(guān)系型數(shù)據(jù)庫(kù))模型,其數(shù)據(jù)按照鍵值對(duì)的形式進(jìn)行組織、索引和存儲(chǔ)。KV存儲(chǔ)非常適合不涉及過(guò)多數(shù)據(jù)關(guān)系業(yè)務(wù)關(guān)系的業(yè)務(wù)數(shù)據(jù),同時(shí)能有效減少讀寫(xiě)磁盤(pán)的次數(shù),比SQL數(shù)據(jù)庫(kù)存儲(chǔ)擁有更好的讀寫(xiě)性能。
目前在生產(chǎn)環(huán)境,使用較多的K-V存儲(chǔ)有Memcached,Redis,LevelDB等。在通信方面,主要使用專有的二進(jìn)制協(xié)議,這樣做的好處是協(xié)議解析的的性能比較高,不足的地方在于通用性差,需要為不同的語(yǔ)言實(shí)現(xiàn)專門(mén)的客戶端,開(kāi)發(fā)成本高,同時(shí)二進(jìn)制協(xié)議的可調(diào)試性差,導(dǎo)致定位問(wèn)題困難;在架構(gòu)設(shè)計(jì)方面,上述存儲(chǔ)的分布式基本都需要客戶端來(lái)實(shí)現(xiàn),Redis從3.0之后開(kāi)始支持集群,但從生產(chǎn)環(huán)境中的測(cè)試情況來(lái)看,單點(diǎn)故障導(dǎo)致集群不可用的情況依然存在,且Redis的定位是緩存,對(duì)于持久化的支持程度有限。
本發(fā)明主要是對(duì)系統(tǒng)中的分布式組件的功能進(jìn)行的改進(jìn),分布式組件向存儲(chǔ)引擎寫(xiě)入數(shù)據(jù)時(shí),能夠根據(jù)Key來(lái)進(jìn)行負(fù)載均衡,將數(shù)據(jù)寫(xiě)入指定的存儲(chǔ)節(jié)點(diǎn)。分布式組件作為客戶端與存儲(chǔ)引擎之間的反向代理,對(duì)客戶端屏蔽負(fù)載均衡的細(xì)節(jié),保證存儲(chǔ)節(jié)點(diǎn)的http接口的透明性。當(dāng)某一個(gè)存儲(chǔ)節(jié)點(diǎn)宕機(jī)時(shí),HA會(huì)自動(dòng)對(duì)數(shù)據(jù)寫(xiě)請(qǐng)求進(jìn)行負(fù)載均衡,保證整個(gè)系統(tǒng)依然可用,從而解決KV存儲(chǔ)的單點(diǎn)限制。
另外,分布式組件中的每個(gè)節(jié)點(diǎn)都是獨(dú)立的,當(dāng)某一HA節(jié)點(diǎn)宕機(jī)時(shí),LVS會(huì)自動(dòng)將數(shù)據(jù)寫(xiě)請(qǐng)求發(fā)送至分布式組件中的其他可用的HA節(jié)點(diǎn),從而解決了HA的單點(diǎn)限制。當(dāng)需要提高系統(tǒng)的吞吐率時(shí),也只需要簡(jiǎn)單地增加HA節(jié)點(diǎn)即可實(shí)現(xiàn)。
數(shù)據(jù)同步模塊在設(shè)計(jì)上有兩種模式,模式一:放在HA的實(shí)現(xiàn)中,和HA的master進(jìn)程耦合在一起(不可能放在worker中,因?yàn)镹ginx的進(jìn)程模型是1master-N worker,而數(shù)據(jù)同步的服務(wù)只能存在于一個(gè)進(jìn)程中)。模式二:作為單獨(dú)的服務(wù),即,將數(shù)據(jù)同步模塊和HA分離。模式一的好處是開(kāi)發(fā)簡(jiǎn)單,部署簡(jiǎn)單,缺點(diǎn)是會(huì)當(dāng)數(shù)據(jù)同步模塊崩潰時(shí),會(huì)導(dǎo)致HA的master進(jìn)程一起退出,從而使HA的單節(jié)點(diǎn)喪失高可用性,生產(chǎn)環(huán)境中這會(huì)帶來(lái)巨大的風(fēng)險(xiǎn)。模式二的好處是服務(wù)隔離,進(jìn)程隔離,HA不再和數(shù)據(jù)同步模塊耦合在一起,兩者僅僅通過(guò)文件即可協(xié)同完成數(shù)據(jù)同步的功能,當(dāng)數(shù)據(jù)同步模塊意外退出時(shí),HA的master進(jìn)程不受影響,服務(wù)整體依然可用,缺點(diǎn)是開(kāi)發(fā)和部署的工作量增大。HustDB HA最終選擇模式二來(lái)完成數(shù)據(jù)同步模塊,這樣的設(shè)計(jì)使得HA的復(fù)雜度大大降低,無(wú)需關(guān)注數(shù)據(jù)同步的細(xì)節(jié),只需要將不一致的數(shù)據(jù)記錄成日志(binlog)即可,在極大程度上提高了HA以及整個(gè)存儲(chǔ)系統(tǒng)的高可用性,并保證集群數(shù)據(jù)的最終一致性。
目前業(yè)界主流的存儲(chǔ)對(duì)于replica的實(shí)現(xiàn)存在兩種模式:
模式一:1Primary-1Replica Shard
模式二:1Primary-N Replica Shards
HustDB HA選用了工程上更加可行的模式一。模式二由于一份數(shù)據(jù)具有更多的備份,因此具備更高的的可用性,但同時(shí)帶來(lái)了更多的數(shù)據(jù)一致性問(wèn)題和實(shí)現(xiàn)的復(fù)雜度。模式一在高可用性方面不如模式二,但在實(shí)現(xiàn)難度方面要小很多,且Hustdb HA自身的定位是分布式KV存儲(chǔ),而不是分布式數(shù)據(jù)庫(kù),因此相對(duì)而言,模式一更加適用。
在本發(fā)明中,分布式組件可以由Nginx服務(wù)器實(shí)現(xiàn),Nginx是高吞吐高并發(fā)的http反向代理,由于HustDB HA并不需要對(duì)存儲(chǔ)節(jié)點(diǎn)上的數(shù)據(jù)進(jìn)行合并(merge),因此為了提高系統(tǒng)的吞吐量和并發(fā)量,HA的進(jìn)程模型為1master-N worker,其中master進(jìn)程會(huì)對(duì)worker進(jìn)程進(jìn)行自動(dòng)?;睿@一點(diǎn)保證了HA單個(gè)節(jié)點(diǎn)的高可用性和高吞吐性。由于各個(gè)進(jìn)程是獨(dú)立的,因此對(duì)于少部分用到共享數(shù)據(jù)的接口,需要利用共享內(nèi)存來(lái)進(jìn)行通信。
Nginx服務(wù)器現(xiàn)有的負(fù)載均衡策略將存儲(chǔ)節(jié)點(diǎn)地址等細(xì)節(jié)完全對(duì)外屏蔽了,也就是說(shuō),對(duì)于開(kāi)發(fā)者來(lái)說(shuō)這些細(xì)節(jié)是透明的,因此,無(wú)法將數(shù)據(jù)寫(xiě)入指定的存儲(chǔ)節(jié)點(diǎn),從而限定了定制化的負(fù)載均衡的實(shí)現(xiàn),本發(fā)明提供的數(shù)據(jù)寫(xiě)請(qǐng)求處理方法及裝置能夠?qū)崿F(xiàn)定制化的負(fù)載均衡,實(shí)現(xiàn)將數(shù)據(jù)寫(xiě)入指定的存儲(chǔ)節(jié)點(diǎn)。
在上述系統(tǒng)框架下,本發(fā)明提供了數(shù)據(jù)寫(xiě)請(qǐng)求處理方法的幾個(gè)實(shí)施例,該方法基于調(diào)用端發(fā)送的數(shù)據(jù)寫(xiě)請(qǐng)求向存儲(chǔ)節(jié)點(diǎn)中寫(xiě)入數(shù)據(jù),其中數(shù)據(jù)寫(xiě)請(qǐng)求包含主請(qǐng)求和至少一個(gè)子請(qǐng)求,對(duì)于調(diào)用端發(fā)送的數(shù)據(jù)寫(xiě)請(qǐng)求可以通過(guò)一個(gè)主請(qǐng)求和至少一個(gè)子請(qǐng)求完成,主請(qǐng)求可以確定向哪些存儲(chǔ)節(jié)點(diǎn)寫(xiě)入數(shù)據(jù),子請(qǐng)求可以向主請(qǐng)求所確定的存儲(chǔ)節(jié)點(diǎn)寫(xiě)入數(shù)據(jù),可以依據(jù)數(shù)據(jù)要寫(xiě)入存儲(chǔ)節(jié)點(diǎn)的個(gè)數(shù)來(lái)確定子請(qǐng)求的個(gè)數(shù),具體描述如下。
圖1示出了根據(jù)本發(fā)明一個(gè)實(shí)施例的數(shù)據(jù)寫(xiě)請(qǐng)求處理方法的流程示意圖。如圖1所示,該方法包括以下步驟:
步驟S100,對(duì)于每一個(gè)子請(qǐng)求,調(diào)用訪問(wèn)接口從全局變量中選擇待寫(xiě)入數(shù)據(jù)的存儲(chǔ)節(jié)點(diǎn)的存儲(chǔ)節(jié)點(diǎn)地址,向存儲(chǔ)節(jié)點(diǎn)發(fā)送子請(qǐng)求,其中將選擇的存儲(chǔ)節(jié)點(diǎn)地址保存至子請(qǐng)求的上下文中。
在本發(fā)明實(shí)施例中,訪問(wèn)接口指可以訪問(wèn)到全局變量的接口,這里訪問(wèn)全局變量是為了從全局變量中選擇待寫(xiě)入數(shù)據(jù)的存儲(chǔ)節(jié)點(diǎn)的存儲(chǔ)節(jié)點(diǎn)地址,以將數(shù)據(jù)寫(xiě)入到對(duì)應(yīng)的存儲(chǔ)節(jié)點(diǎn)中,其中,全局變量中存儲(chǔ)了存儲(chǔ)引擎中所有存儲(chǔ)節(jié)點(diǎn)的存儲(chǔ)節(jié)點(diǎn)地址。在調(diào)用訪問(wèn)接口從全局變量中選擇了待寫(xiě)入數(shù)據(jù)的存儲(chǔ)節(jié)點(diǎn)的存儲(chǔ)節(jié)點(diǎn)地址后,便可以向?qū)?yīng)的存儲(chǔ)節(jié)點(diǎn)發(fā)送子請(qǐng)求了,其中將選擇的存儲(chǔ)節(jié)點(diǎn)地址保存至子請(qǐng)求的上下文中,具體地,生成一個(gè)子請(qǐng)求對(duì)象,將子請(qǐng)求對(duì)象與上下文關(guān)聯(lián)起來(lái),即,將子請(qǐng)求對(duì)象與上下文綁定在一起。其中,上下文指在一個(gè)請(qǐng)求的處理過(guò)程中,把一些關(guān)鍵的信息保存下來(lái)的類似struct這樣的結(jié)構(gòu)體,這里指將選擇的存儲(chǔ)節(jié)點(diǎn)地址保存至子請(qǐng)求的上下文中,以便于在后續(xù)方法步驟中獲取選擇的存儲(chǔ)節(jié)點(diǎn)地址,根據(jù)該存儲(chǔ)節(jié)點(diǎn)地址與存儲(chǔ)節(jié)點(diǎn)建立連接。
步驟S101,從子請(qǐng)求的上下文中提取出所選擇的存儲(chǔ)節(jié)點(diǎn)地址,并保存至存儲(chǔ)節(jié)點(diǎn)的上下文中。
存儲(chǔ)節(jié)點(diǎn)地址是分布式組件與存儲(chǔ)節(jié)點(diǎn)建立連接的關(guān)鍵,這里還需要從子請(qǐng)求的上下文中提取出所選擇的存儲(chǔ)節(jié)點(diǎn)地址,并保存至存儲(chǔ)節(jié)點(diǎn)的上下文中。具體地,子請(qǐng)求的上下文中可能包含了多個(gè)信息,每個(gè)信息都對(duì)應(yīng)有相應(yīng)的屬性字段,可以根據(jù)地址屬性字段從子請(qǐng)求的上下文中提取出地址屬性字段對(duì)應(yīng)的存儲(chǔ)節(jié)點(diǎn)地址,并將提取出的存儲(chǔ)節(jié)點(diǎn)地址保存至存儲(chǔ)節(jié)點(diǎn)的上下文中。
步驟S102,從存儲(chǔ)節(jié)點(diǎn)的上下文中提取出存儲(chǔ)節(jié)點(diǎn)地址,與存儲(chǔ)節(jié)點(diǎn)建立連接,將數(shù)據(jù)寫(xiě)入到相應(yīng)的存儲(chǔ)節(jié)點(diǎn)。
在將存儲(chǔ)節(jié)點(diǎn)地址保存至存儲(chǔ)節(jié)點(diǎn)的上下文之后,便可以在分布式組件與存儲(chǔ)節(jié)點(diǎn)之間建立連接,具體地,可以從存儲(chǔ)節(jié)點(diǎn)的上下文中提取出存儲(chǔ)節(jié)點(diǎn)地址,與存儲(chǔ)節(jié)點(diǎn)建立連接,將數(shù)據(jù)寫(xiě)入到相應(yīng)的存儲(chǔ)節(jié)點(diǎn)。
根據(jù)本發(fā)明上述實(shí)施例提供的方法,對(duì)于一個(gè)子請(qǐng)求,調(diào)用訪問(wèn)接口從全局變量中選擇待寫(xiě)入數(shù)據(jù)的存儲(chǔ)節(jié)點(diǎn)的存儲(chǔ)節(jié)點(diǎn)地址,向存儲(chǔ)節(jié)點(diǎn)發(fā)送子請(qǐng)求,其中將選擇的存儲(chǔ)節(jié)點(diǎn)地址保存至子請(qǐng)求的上下文中,從子請(qǐng)求的上下文中提取出所選擇的存儲(chǔ)節(jié)點(diǎn)地址,并保存至存儲(chǔ)節(jié)點(diǎn)的上下文中,從存儲(chǔ)節(jié)點(diǎn)的上下文中提取出存儲(chǔ)節(jié)點(diǎn)地址,與存儲(chǔ)節(jié)點(diǎn)建立連接,將數(shù)據(jù)寫(xiě)入到相應(yīng)的存儲(chǔ)節(jié)點(diǎn)。在本實(shí)施例中,利用全局變量記錄存儲(chǔ)節(jié)點(diǎn)的存儲(chǔ)節(jié)點(diǎn)地址,而且該全局變量提供有供訪問(wèn)的訪問(wèn)接口,通過(guò)調(diào)用該訪問(wèn)接口即可獲取待寫(xiě)入數(shù)據(jù)的存儲(chǔ)節(jié)點(diǎn)的存儲(chǔ)節(jié)點(diǎn)地址,使存儲(chǔ)節(jié)點(diǎn)地址暴露出來(lái),從而能夠滿足調(diào)用端的定制化要求向指定存儲(chǔ)節(jié)點(diǎn)寫(xiě)入數(shù)據(jù),實(shí)現(xiàn)了定制化的負(fù)載均衡,解決了KV存儲(chǔ)的單點(diǎn)限制。
圖2示出了根據(jù)本發(fā)明另一個(gè)實(shí)施例的數(shù)據(jù)寫(xiě)請(qǐng)求處理方法的流程示意圖。在圖2所示實(shí)施例中將以分布式組件為Nginx服務(wù)器為例進(jìn)行詳細(xì)介紹。
Nginx服務(wù)器是以全異步非阻塞的方式運(yùn)行,Nginx服務(wù)器所執(zhí)行數(shù)據(jù)寫(xiě)請(qǐng)求處理方法步驟可以分為Nginx主循環(huán)和Nginx子循環(huán)(子請(qǐng)求的處理過(guò)程),其中,Nginx主循環(huán)包括步驟S200-步驟S203、步驟S208-步驟S209;Nginx子循環(huán)包括步驟S204-步驟S207,下面針對(duì)各個(gè)方法步驟做詳細(xì)介紹:
步驟S200,在主循環(huán)中,調(diào)用用于處理子請(qǐng)求的處理器的入口函數(shù)。
為了能夠?qū)崿F(xiàn)多個(gè)子請(qǐng)求可以自動(dòng)串行執(zhí)行,本實(shí)施例預(yù)先創(chuàng)建用于處理子請(qǐng)求的處理的入口函數(shù)addon_handler。一旦進(jìn)入Nginx主循環(huán)中,首先調(diào)用用于處理子請(qǐng)求的處理的入口函數(shù)addon_handler,利用用于處理子請(qǐng)求的處理器來(lái)處理子請(qǐng)求。針對(duì)每一個(gè)子請(qǐng)求,都需要執(zhí)行步驟S204-步驟S206,也就是說(shuō),當(dāng)一個(gè)子請(qǐng)求執(zhí)行完后,在回到主循環(huán)過(guò)程中后,通過(guò)調(diào)用用于處理子請(qǐng)求的處理器的入口函數(shù),利用用于處理子請(qǐng)求的處理器處理下一個(gè)子請(qǐng)求。
步驟S201,獲取主請(qǐng)求的上下文。
數(shù)據(jù)寫(xiě)請(qǐng)求包含主請(qǐng)求和至少一個(gè)子請(qǐng)求,主請(qǐng)求的上下文中記錄了向哪些存儲(chǔ)節(jié)點(diǎn)寫(xiě)入數(shù)據(jù),這里獲取主請(qǐng)求的上下文是為了根據(jù)主請(qǐng)求的上下文的記載確定向哪些存儲(chǔ)節(jié)點(diǎn)發(fā)送子請(qǐng)求。
步驟S202,判斷主請(qǐng)求的上下文是否已創(chuàng)建,若否,則執(zhí)行步驟S203;若是,則執(zhí)行步驟S208。
這里判斷主請(qǐng)求的上下文是否創(chuàng)建主要是為了確定對(duì)應(yīng)的數(shù)據(jù)寫(xiě)請(qǐng)求是否是調(diào)用端發(fā)起的新的數(shù)據(jù)寫(xiě)請(qǐng)求。如果是新的數(shù)據(jù)寫(xiě)請(qǐng)求,對(duì)應(yīng)的主請(qǐng)求的上下文還未創(chuàng)建,需要?jiǎng)?chuàng)建主請(qǐng)求的上下文。判斷出主請(qǐng)求的上下文已創(chuàng)建,則說(shuō)明前面已經(jīng)處理過(guò)該數(shù)據(jù)寫(xiě)請(qǐng)求,此時(shí)需要確定是否已向主請(qǐng)求的上下文中所記錄的全部存儲(chǔ)節(jié)點(diǎn)都寫(xiě)入數(shù)據(jù),具體地,可以判斷待寫(xiě)入數(shù)據(jù)的存儲(chǔ)節(jié)點(diǎn)是否為空。
步驟S203,創(chuàng)建主請(qǐng)求的上下文,并將主請(qǐng)求的上下文與主請(qǐng)求關(guān)聯(lián)。
在判斷出主請(qǐng)求的上下文未創(chuàng)建的情況下,可以創(chuàng)建主請(qǐng)求的上下文,將主請(qǐng)求的上下文與主請(qǐng)求關(guān)聯(lián),具體地,生成一個(gè)主請(qǐng)求對(duì)象,將主請(qǐng)求對(duì)象與上下文關(guān)聯(lián)起來(lái),即,將主請(qǐng)求對(duì)象與上下文綁定在一起。
步驟S204,對(duì)于每一個(gè)子請(qǐng)求,調(diào)用訪問(wèn)接口從全局變量中選擇待寫(xiě)入數(shù)據(jù)的存儲(chǔ)節(jié)點(diǎn)的存儲(chǔ)節(jié)點(diǎn)地址,向存儲(chǔ)節(jié)點(diǎn)發(fā)送子請(qǐng)求,其中將選擇的存儲(chǔ)節(jié)點(diǎn)地址保存至子請(qǐng)求的上下文中。
本發(fā)明中,HA要解決的最重要的問(wèn)題之一是負(fù)載均衡,這是讓存儲(chǔ)引擎從單點(diǎn)擴(kuò)充為集群的基礎(chǔ)。而支持調(diào)用端選擇存儲(chǔ)節(jié)點(diǎn)(Customized Peer Selector)是實(shí)現(xiàn)定制化的負(fù)載均衡的關(guān)鍵。本實(shí)施例方案支持HA往指定的ip:port的存儲(chǔ)節(jié)點(diǎn)發(fā)送子請(qǐng)求,存儲(chǔ)節(jié)點(diǎn)的地址(uri)是參數(shù)化的,可傳入的。支持調(diào)用端選擇存儲(chǔ)節(jié)點(diǎn)依賴于一系列Nginx內(nèi)置的數(shù)據(jù)結(jié)構(gòu)。
本實(shí)施例中,當(dāng)HA加載配置文件時(shí),獲取存儲(chǔ)節(jié)點(diǎn)地址列表相關(guān)的配置信息;將存儲(chǔ)節(jié)點(diǎn)地址列表保存到全局變量中,生成全局變量的訪問(wèn)接口。
在一個(gè)具體的實(shí)施例中,當(dāng)HA加載配置文件時(shí),如發(fā)現(xiàn)名為customized_selector的上游存儲(chǔ)節(jié)點(diǎn)的配置項(xiàng)時(shí),會(huì)設(shè)置初始化函數(shù)為ngx_http_peer_selector_init,之后在upstream進(jìn)行初始化時(shí),會(huì)調(diào)用此函數(shù),將上游存儲(chǔ)節(jié)點(diǎn)地址列表保存至全局變量g_peer_selector_backends中,并通過(guò)函數(shù)ngx_http_get_backends對(duì)外提供訪問(wèn)接口。HA通過(guò)訪問(wèn)接口ngx_http_get_backends獲取到上游存儲(chǔ)節(jié)點(diǎn)地址列表后,可完成負(fù)載均衡表的構(gòu)建過(guò)程。
在調(diào)用訪問(wèn)接口從全局變量中選擇了待寫(xiě)入數(shù)據(jù)的存儲(chǔ)節(jié)點(diǎn)的存儲(chǔ)節(jié)點(diǎn)地址后,便可以向?qū)?yīng)的存儲(chǔ)節(jié)點(diǎn)發(fā)送子請(qǐng)求了,其中將選擇的存儲(chǔ)節(jié)點(diǎn)地址保存至子請(qǐng)求的上下文中,具體地,生成一個(gè)子請(qǐng)求對(duì)象,將子請(qǐng)求對(duì)象與上下文關(guān)聯(lián)起來(lái),即,將子請(qǐng)求對(duì)象與上下文綁定在一起。其中,上下文指在一個(gè)請(qǐng)求的處理過(guò)程中,把一些關(guān)鍵的信息保存下來(lái)的類似struct這樣的結(jié)構(gòu)體,這里指將選擇的存儲(chǔ)節(jié)點(diǎn)地址保存至子請(qǐng)求的上下文中,以便于在后續(xù)方法步驟中獲取選擇的存儲(chǔ)節(jié)點(diǎn)地址,根據(jù)該存儲(chǔ)節(jié)點(diǎn)地址與存儲(chǔ)節(jié)點(diǎn)建立連接。在本步驟中,具體可以通過(guò)函數(shù)ngx_http_set_addon_module_ctx將選擇的存儲(chǔ)節(jié)點(diǎn)地址保存至子請(qǐng)求的上下文中。
步驟S205,從子請(qǐng)求的上下文中提取出所選擇的存儲(chǔ)節(jié)點(diǎn)地址,并保存至存儲(chǔ)節(jié)點(diǎn)的上下文中。
存儲(chǔ)節(jié)點(diǎn)地址是分布式組件與存儲(chǔ)節(jié)點(diǎn)建立連接的關(guān)鍵,這里還需要從子請(qǐng)求的上下文中提取出所選擇的存儲(chǔ)節(jié)點(diǎn)地址,并保存至存儲(chǔ)節(jié)點(diǎn)的上下文中。具體地,子請(qǐng)求的上下文中可能包含了多個(gè)信息,每個(gè)信息都對(duì)應(yīng)有相應(yīng)的屬性字段,可以根據(jù)地址屬性字段從子請(qǐng)求的上下文中提取出地址屬性字段對(duì)應(yīng)的存儲(chǔ)節(jié)點(diǎn)地址,并將提取出的存儲(chǔ)節(jié)點(diǎn)地址保存至存儲(chǔ)節(jié)點(diǎn)的上下文中。在本步驟中,具體可以通過(guò)ngx_http_peer_selector_module將之前保存至子請(qǐng)求的上下文中的存儲(chǔ)節(jié)點(diǎn)地址提取出來(lái),并保存至存儲(chǔ)節(jié)點(diǎn)的上下文中。
步驟S206,從存儲(chǔ)節(jié)點(diǎn)的上下文中提取出存儲(chǔ)節(jié)點(diǎn)地址,與存儲(chǔ)節(jié)點(diǎn)建立連接,將數(shù)據(jù)寫(xiě)入到相應(yīng)的存儲(chǔ)節(jié)點(diǎn)。
在本步驟中,具體可以通過(guò)ngx_http_peer_selector_module將之前保存至存儲(chǔ)節(jié)點(diǎn)的上下文中的存儲(chǔ)節(jié)點(diǎn)地址提取出來(lái),通過(guò)Nginx服務(wù)器的內(nèi)置函數(shù)ngx_http_upstream_connect與存儲(chǔ)節(jié)點(diǎn)建立連接,例如,TCP連接,將數(shù)據(jù)寫(xiě)入到相應(yīng)的存儲(chǔ)節(jié)點(diǎn)。
步驟S207,調(diào)用子請(qǐng)求完成回調(diào)函數(shù)。
調(diào)用子請(qǐng)求完成回調(diào)函數(shù),可以回到Nginx主循環(huán)過(guò)程中,在回到主循環(huán)中后,便可以再次調(diào)用用于處理子請(qǐng)求的處理器的入口函數(shù),利用用于處理子請(qǐng)求的處理器處理下一個(gè)子請(qǐng)求。
由于HustDB HA采用了1Primary-1Replica Shard的存儲(chǔ)模式,每次寫(xiě)操作都涉及到對(duì)Primary和Replica Shard兩個(gè)節(jié)點(diǎn)的串行訪問(wèn),這依賴于串行子請(qǐng)求(Sequential Subrequests)的技術(shù)實(shí)現(xiàn)。串行子請(qǐng)求是Nginx http開(kāi)發(fā)中難度最大的技術(shù)點(diǎn)之一。正確進(jìn)行串行子請(qǐng)求編程的關(guān)鍵,是將上游存儲(chǔ)節(jié)點(diǎn)選擇的控制權(quán)從Nginx內(nèi)核轉(zhuǎn)移到上層,即每一次子請(qǐng)求結(jié)束之后,Nginx都會(huì)調(diào)用子請(qǐng)求完成回調(diào)函數(shù)回到主循環(huán)過(guò)程中,在主循環(huán)過(guò)程中再次調(diào)用用于處理子請(qǐng)求的處理器的入口函數(shù),實(shí)現(xiàn)了前一個(gè)子請(qǐng)求結(jié)束之后,讓后一個(gè)子請(qǐng)求自動(dòng)發(fā)出去,從而將多個(gè)子請(qǐng)求串起來(lái)自動(dòng)化。這樣Nginx處理器可以決定子請(qǐng)求轉(zhuǎn)發(fā)的上游存儲(chǔ)節(jié)點(diǎn)地址。
本實(shí)施例中串行子請(qǐng)求的投遞方法并非用常規(guī)的for循環(huán)方式實(shí)現(xiàn),而是利用創(chuàng)建子請(qǐng)求的狀態(tài)機(jī)模型實(shí)現(xiàn)。每一個(gè)子請(qǐng)求發(fā)出去之后,Nginx將回到主循環(huán)中,等待下一個(gè)事件的觸發(fā)。因此所有跨越子請(qǐng)求的上下文,都需要自行保存下來(lái)。在本發(fā)明的一種可選實(shí)施方式中,在將數(shù)據(jù)寫(xiě)入到相應(yīng)的存儲(chǔ)節(jié)點(diǎn)之后,方法還包括:保存子請(qǐng)求的上下文。
步驟S208,判斷待寫(xiě)入數(shù)據(jù)的存儲(chǔ)節(jié)點(diǎn)是否為空,若是,則執(zhí)行步驟S209;若否,則執(zhí)行步驟S204。
這里判斷待寫(xiě)入數(shù)據(jù)的存儲(chǔ)節(jié)點(diǎn)是否為空,是為了確定待寫(xiě)入數(shù)據(jù)的存儲(chǔ)節(jié)點(diǎn)是否已經(jīng)寫(xiě)入了數(shù)據(jù),若待寫(xiě)入數(shù)據(jù)的存儲(chǔ)節(jié)點(diǎn)為空,則說(shuō)明待寫(xiě)入數(shù)據(jù)的存儲(chǔ)節(jié)點(diǎn)都已經(jīng)寫(xiě)入了數(shù)據(jù);若待寫(xiě)入數(shù)據(jù)的存儲(chǔ)節(jié)點(diǎn)不為空,則說(shuō)明待寫(xiě)入數(shù)據(jù)的存儲(chǔ)節(jié)點(diǎn)還未都寫(xiě)入了數(shù)據(jù),需要執(zhí)行子請(qǐng)求的步驟。
舉例說(shuō)明,假設(shè)需要向2個(gè)存儲(chǔ)節(jié)點(diǎn)寫(xiě)入數(shù)據(jù),這里判斷待寫(xiě)入數(shù)據(jù)的存儲(chǔ)節(jié)點(diǎn)是否為空就是要判斷這2個(gè)存儲(chǔ)節(jié)點(diǎn)是否都已寫(xiě)入數(shù)據(jù),若有一個(gè)存儲(chǔ)節(jié)點(diǎn)還未寫(xiě)入數(shù)據(jù),則需要執(zhí)行子請(qǐng)求的步驟。
步驟S209,向發(fā)送數(shù)據(jù)寫(xiě)請(qǐng)求的調(diào)用端返回響應(yīng)結(jié)果。
在存儲(chǔ)節(jié)點(diǎn)為空的情況下,說(shuō)明待寫(xiě)入數(shù)據(jù)的存儲(chǔ)節(jié)點(diǎn)都已經(jīng)寫(xiě)入了數(shù)據(jù),此時(shí)可以向發(fā)送數(shù)據(jù)寫(xiě)請(qǐng)求的調(diào)用端返回響應(yīng)結(jié)果,例如,響應(yīng)結(jié)果可以是數(shù)據(jù)已寫(xiě)入到XX存儲(chǔ)節(jié)點(diǎn)。
在本發(fā)明的一種可選實(shí)施方式中,子請(qǐng)求的上下文中定義有狀態(tài)字段,這里的狀態(tài)字段標(biāo)識(shí)了數(shù)據(jù)寫(xiě)請(qǐng)求所處的階段;將數(shù)據(jù)寫(xiě)入到相應(yīng)的存儲(chǔ)節(jié)點(diǎn)表明一個(gè)子請(qǐng)求執(zhí)行結(jié)束,因此,在將數(shù)據(jù)寫(xiě)入到相應(yīng)的存儲(chǔ)節(jié)點(diǎn)之后,還需要更新子請(qǐng)求的上下文的狀態(tài)字段;用于處理子請(qǐng)求的處理器處理下一個(gè)子請(qǐng)求具體為:用于處理子請(qǐng)求的處理器根據(jù)更新的狀態(tài)字段識(shí)別出數(shù)據(jù)寫(xiě)請(qǐng)求所處的階段,以便處理下一個(gè)子請(qǐng)求。
上述可選的實(shí)施方式所要解決的問(wèn)題是在addon_handler中區(qū)分當(dāng)前所處的階段。對(duì)于每一個(gè)新的主請(qǐng)求對(duì)象,當(dāng)Nginx第一次調(diào)用addon_handler的時(shí)候,跟主請(qǐng)求關(guān)聯(lián)的上下文對(duì)象是不存在的,利用這個(gè)特點(diǎn)可以區(qū)分當(dāng)前是否是第一次調(diào)用addon_handler。之后的子請(qǐng)求,就需要更新上下文中定義的狀態(tài)字段,通過(guò)該狀態(tài)字段的值來(lái)判定當(dāng)前處于什么階段。上述的流程以上游存儲(chǔ)節(jié)點(diǎn)是否遍歷完畢作為判定標(biāo)志。當(dāng)遍歷完畢時(shí),可以將處理結(jié)果返回給客戶端了,串行子請(qǐng)求將終止在這一輪調(diào)用。
本實(shí)施例的流程中所涉及的關(guān)鍵階段如下:
1)ngx_http_run_posted_requests是控制整個(gè)流程循環(huán)的中樞;
2)addon_handler會(huì)被ngx_http_core_content_phase所調(diào)用,這是Nginx的內(nèi)容解析階段;
3)ngx_http_subrequest用于發(fā)送子請(qǐng)求,之后會(huì)進(jìn)入反向代理的處理過(guò)程ngx_http_proxy_handler;
4)子請(qǐng)求完成后的回調(diào)函數(shù)會(huì)被ngx_http_finalize_request所調(diào)用,回調(diào)函數(shù)需要設(shè)置父請(qǐng)求的寫(xiě)事件處理器為ngx_http_core_run_phases,以便Nginx能再次調(diào)用到addon_handler。
根據(jù)本發(fā)明上述實(shí)施例提供的方法,一方面,利用全局變量記錄存儲(chǔ)節(jié)點(diǎn)的存儲(chǔ)節(jié)點(diǎn)地址,而且該全局變量提供有供訪問(wèn)的訪問(wèn)接口,通過(guò)調(diào)用該訪問(wèn)接口即可獲取待寫(xiě)入數(shù)據(jù)的存儲(chǔ)節(jié)點(diǎn)的存儲(chǔ)節(jié)點(diǎn)地址,使存儲(chǔ)節(jié)點(diǎn)地址暴露出來(lái),從而能夠滿足調(diào)用端的定制化要求向指定存儲(chǔ)節(jié)點(diǎn)寫(xiě)入數(shù)據(jù),實(shí)現(xiàn)了定制化的負(fù)載均衡,解決了KV存儲(chǔ)的單點(diǎn)限制。另一方面,每一次子請(qǐng)求結(jié)束之后,Nginx都會(huì)調(diào)用子請(qǐng)求完成回調(diào)函數(shù)回到主循環(huán)過(guò)程中,在主循環(huán)過(guò)程中再次調(diào)用用于處理子請(qǐng)求的處理器的入口函數(shù),實(shí)現(xiàn)了前一個(gè)子請(qǐng)求結(jié)束之后,讓后一個(gè)子請(qǐng)求自動(dòng)發(fā)出去,從而將多個(gè)子請(qǐng)求串起來(lái)自動(dòng)化,大大提升了數(shù)據(jù)寫(xiě)請(qǐng)求的處理效率。
圖3示出了根據(jù)本發(fā)明一個(gè)實(shí)施例的數(shù)據(jù)寫(xiě)請(qǐng)求處理裝置的結(jié)構(gòu)示意圖。如圖3所示,該裝置30包括:用于處理子請(qǐng)求的處理器300;其中,用于處理子請(qǐng)求的處理器300包括:
選擇單元301,適于對(duì)于每一個(gè)子請(qǐng)求,調(diào)用訪問(wèn)接口從全局變量中選擇待寫(xiě)入數(shù)據(jù)的存儲(chǔ)節(jié)點(diǎn)的存儲(chǔ)節(jié)點(diǎn)地址。
子請(qǐng)求處理單元302,適于向存儲(chǔ)節(jié)點(diǎn)發(fā)送子請(qǐng)求,其中將選擇的存儲(chǔ)節(jié)點(diǎn)地址保存至子請(qǐng)求的上下文中。
提取單元303,適于從子請(qǐng)求的上下文中提取出所選擇的存儲(chǔ)節(jié)點(diǎn)地址。
上下文寫(xiě)入單元304,適于將提取出的存儲(chǔ)節(jié)點(diǎn)地址保存至存儲(chǔ)節(jié)點(diǎn)的上下文中。
連接單元305,適于從存儲(chǔ)節(jié)點(diǎn)的上下文中提取出存儲(chǔ)節(jié)點(diǎn)地址,與存儲(chǔ)節(jié)點(diǎn)建立連接。
數(shù)據(jù)寫(xiě)入單元306,適于將數(shù)據(jù)寫(xiě)入到相應(yīng)的存儲(chǔ)節(jié)點(diǎn)。
根據(jù)本發(fā)明上述實(shí)施例提供的裝置,對(duì)于每一個(gè)子請(qǐng)求,調(diào)用訪問(wèn)接口從全局變量中選擇待寫(xiě)入數(shù)據(jù)的存儲(chǔ)節(jié)點(diǎn)的存儲(chǔ)節(jié)點(diǎn)地址,向存儲(chǔ)節(jié)點(diǎn)發(fā)送子請(qǐng)求,其中將選擇的存儲(chǔ)節(jié)點(diǎn)地址保存至子請(qǐng)求的上下文中,從子請(qǐng)求的上下文中提取出所選擇的存儲(chǔ)節(jié)點(diǎn)地址,并保存至存儲(chǔ)節(jié)點(diǎn)的上下文中,從存儲(chǔ)節(jié)點(diǎn)的上下文中提取出存儲(chǔ)節(jié)點(diǎn)地址,與存儲(chǔ)節(jié)點(diǎn)建立連接,將數(shù)據(jù)寫(xiě)入到相應(yīng)的存儲(chǔ)節(jié)點(diǎn)。在本實(shí)施例中,利用全局變量記錄存儲(chǔ)節(jié)點(diǎn)的存儲(chǔ)節(jié)點(diǎn)地址,而且該全局變量提供有供訪問(wèn)的訪問(wèn)接口,通過(guò)調(diào)用該訪問(wèn)接口即可獲取待寫(xiě)入數(shù)據(jù)的存儲(chǔ)節(jié)點(diǎn)的存儲(chǔ)節(jié)點(diǎn)地址,使存儲(chǔ)節(jié)點(diǎn)地址暴露出來(lái),從而能夠滿足調(diào)用端的定制化要求向指定存儲(chǔ)節(jié)點(diǎn)寫(xiě)入數(shù)據(jù),實(shí)現(xiàn)了定制化的負(fù)載均衡,解決了KV存儲(chǔ)的單點(diǎn)限制。
圖4示出了根據(jù)本發(fā)明另一個(gè)實(shí)施例的數(shù)據(jù)寫(xiě)請(qǐng)求處理裝置的結(jié)構(gòu)示意圖。與圖3相比,不同之處在于,該裝置包括:
初始化模塊310,適于加載配置文件,獲取存儲(chǔ)節(jié)點(diǎn)地址列表相關(guān)的配置信息;將存儲(chǔ)節(jié)點(diǎn)地址列表保存到全局變量中,生成全局變量的訪問(wèn)接口。
用于處理主請(qǐng)求的處理器320,其中,用于處理主請(qǐng)求的處理器320包括:
獲取單元321,適于獲取主請(qǐng)求的上下文;
第一判斷單元322,適于判斷主請(qǐng)求的上下文是否已創(chuàng)建;
創(chuàng)建單元323,適于若主請(qǐng)求的上下文未創(chuàng)建,創(chuàng)建主請(qǐng)求的上下文;
關(guān)聯(lián)單元324,適于將主請(qǐng)求的上下文與主請(qǐng)求關(guān)聯(lián)。
第二判斷模塊330,適于若主請(qǐng)求的上下文已創(chuàng)建,判斷待寫(xiě)入數(shù)據(jù)的存儲(chǔ)節(jié)點(diǎn)是否為空;
響應(yīng)模塊340,適于若待寫(xiě)入數(shù)據(jù)的存儲(chǔ)節(jié)點(diǎn)為空,向發(fā)送數(shù)據(jù)寫(xiě)請(qǐng)求的調(diào)用端返回響應(yīng)結(jié)果;
用于處理子請(qǐng)求的處理器300具體適于在待寫(xiě)入數(shù)據(jù)的存儲(chǔ)節(jié)點(diǎn)不為空的情況下運(yùn)行。
用于處理子請(qǐng)求的處理器還包括:回調(diào)單元307,適于調(diào)用子請(qǐng)求完成回調(diào)函數(shù),回到主循環(huán)過(guò)程中;
調(diào)用模塊350,適于在主循環(huán)過(guò)程中,調(diào)用用于處理子請(qǐng)求的處理器的入口函數(shù),利用用于處理子請(qǐng)求的處理器處理下一個(gè)子請(qǐng)求。
存儲(chǔ)模塊360,適于保存子請(qǐng)求的上下文。
其中,子請(qǐng)求的上下文中定義有狀態(tài)字段;
用于處理子請(qǐng)求的處理器300還包括:更新單元308,適于更新子請(qǐng)求的上下文的狀態(tài)字段;
用于處理子請(qǐng)求的處理器300具體適于:根據(jù)更新的狀態(tài)字段識(shí)別出數(shù)據(jù)寫(xiě)請(qǐng)求所處的階段,以便處理下一個(gè)子請(qǐng)求。
根據(jù)本發(fā)明上述實(shí)施例提供的裝置,一方面,利用全局變量記錄存儲(chǔ)節(jié)點(diǎn)的存儲(chǔ)節(jié)點(diǎn)地址,而且該全局變量提供有供訪問(wèn)的訪問(wèn)接口,通過(guò)調(diào)用該訪問(wèn)接口即可獲取待寫(xiě)入數(shù)據(jù)的存儲(chǔ)節(jié)點(diǎn)的存儲(chǔ)節(jié)點(diǎn)地址,使存儲(chǔ)節(jié)點(diǎn)地址暴露出來(lái),從而能夠滿足調(diào)用端的定制化要求向指定存儲(chǔ)節(jié)點(diǎn)寫(xiě)入數(shù)據(jù),實(shí)現(xiàn)了定制化的負(fù)載均衡,解決了KV存儲(chǔ)的單點(diǎn)限制。另一方面,每一次子請(qǐng)求結(jié)束之后,Nginx都會(huì)調(diào)用子請(qǐng)求完成回調(diào)函數(shù)回到主循環(huán)過(guò)程中,在主循環(huán)過(guò)程中再次調(diào)用用于處理子請(qǐng)求的處理器的入口函數(shù),實(shí)現(xiàn)了前一個(gè)子請(qǐng)求結(jié)束之后,讓后一個(gè)子請(qǐng)求自動(dòng)發(fā)出去,從而將多個(gè)子請(qǐng)求串起來(lái)自動(dòng)化,大大提升了數(shù)據(jù)寫(xiě)請(qǐng)求的處理效率。
圖5示出了根據(jù)本發(fā)明一個(gè)實(shí)施例的分布式數(shù)據(jù)存儲(chǔ)系統(tǒng)的結(jié)構(gòu)示意圖。如圖5所示,該系統(tǒng)500包括:調(diào)用端510、分布式組件520和存儲(chǔ)節(jié)點(diǎn)530;其中,分布式組件520包括數(shù)據(jù)寫(xiě)請(qǐng)求處理裝置30。
根據(jù)本發(fā)明上述實(shí)施例提供的系統(tǒng),一方面,利用全局變量記錄存儲(chǔ)節(jié)點(diǎn)的存儲(chǔ)節(jié)點(diǎn)地址,而且該全局變量提供有供訪問(wèn)的訪問(wèn)接口,通過(guò)調(diào)用該訪問(wèn)接口即可獲取待寫(xiě)入數(shù)據(jù)的存儲(chǔ)節(jié)點(diǎn)的存儲(chǔ)節(jié)點(diǎn)地址,使存儲(chǔ)節(jié)點(diǎn)地址暴露出來(lái),從而能夠滿足調(diào)用端的定制化要求向指定存儲(chǔ)節(jié)點(diǎn)寫(xiě)入數(shù)據(jù),實(shí)現(xiàn)了定制化的負(fù)載均衡,解決了KV存儲(chǔ)的單點(diǎn)限制。另一方面,每一次子請(qǐng)求結(jié)束之后,Nginx都會(huì)調(diào)用子請(qǐng)求完成回調(diào)函數(shù)回到主循環(huán)過(guò)程中,在主循環(huán)過(guò)程中再次調(diào)用用于處理子請(qǐng)求的處理器的入口函數(shù),實(shí)現(xiàn)了前一個(gè)子請(qǐng)求結(jié)束之后,讓后一個(gè)子請(qǐng)求自動(dòng)發(fā)出去,從而將多個(gè)子請(qǐng)求串起來(lái)自動(dòng)化,大大提升了數(shù)據(jù)寫(xiě)請(qǐng)求的處理效率。
在此提供的算法和顯示不與任何特定計(jì)算機(jī)、虛擬系統(tǒng)或者其它設(shè)備固有相關(guān)。各種通用系統(tǒng)也可以與基于在此的示教一起使用。根據(jù)上面的描述,構(gòu)造這類系統(tǒng)所要求的結(jié)構(gòu)是顯而易見(jiàn)的。此外,本發(fā)明也不針對(duì)任何特定編程語(yǔ)言。應(yīng)當(dāng)明白,可以利用各種編程語(yǔ)言實(shí)現(xiàn)在此描述的本發(fā)明的內(nèi)容,并且上面對(duì)特定語(yǔ)言所做的描述是為了披露本發(fā)明的最佳實(shí)施方式。
在此處所提供的說(shuō)明書(shū)中,說(shuō)明了大量具體細(xì)節(jié)。然而,能夠理解,本發(fā)明的實(shí)施例可以在沒(méi)有這些具體細(xì)節(jié)的情況下實(shí)踐。在一些實(shí)例中,并未詳細(xì)示出公知的方法、結(jié)構(gòu)和技術(shù),以便不模糊對(duì)本說(shuō)明書(shū)的理解。
類似地,應(yīng)當(dāng)理解,為了精簡(jiǎn)本公開(kāi)并幫助理解各個(gè)發(fā)明方面中的一個(gè)或多個(gè),在上面對(duì)本發(fā)明的示例性實(shí)施例的描述中,本發(fā)明的各個(gè)特征有時(shí)被一起分組到單個(gè)實(shí)施例、圖、或者對(duì)其的描述中。然而,并不應(yīng)將該公開(kāi)的方法解釋成反映如下意圖:即所要求保護(hù)的本發(fā)明要求比在每個(gè)權(quán)利要求中所明確記載的特征更多的特征。更確切地說(shuō),如下面的權(quán)利要求書(shū)所反映的那樣,發(fā)明方面在于少于前面公開(kāi)的單個(gè)實(shí)施例的所有特征。因此,遵循具體實(shí)施方式的權(quán)利要求書(shū)由此明確地并入該具體實(shí)施方式,其中每個(gè)權(quán)利要求本身都作為本發(fā)明的單獨(dú)實(shí)施例。
本領(lǐng)域那些技術(shù)人員可以理解,可以對(duì)實(shí)施例中的設(shè)備中的模塊進(jìn)行自適應(yīng)性地改變并且把它們?cè)O(shè)置在與該實(shí)施例不同的一個(gè)或多個(gè)設(shè)備中??梢园褜?shí)施例中的模塊或單元或組件組合成一個(gè)模塊或單元或組件,以及此外可以把它們分成多個(gè)子模塊或子單元或子組件。除了這樣的特征和/或過(guò)程或者單元中的至少一些是相互排斥之外,可以采用任何組合對(duì)本說(shuō)明書(shū)(包括伴隨的權(quán)利要求、摘要和附圖)中公開(kāi)的所有特征以及如此公開(kāi)的任何方法或者設(shè)備的所有過(guò)程或單元進(jìn)行組合。除非另外明確陳述,本說(shuō)明書(shū)(包括伴隨的權(quán)利要求、摘要和附圖)中公開(kāi)的每個(gè)特征可以由提供相同、等同或相似目的的替代特征來(lái)代替。
此外,本領(lǐng)域的技術(shù)人員能夠理解,盡管在此所述的一些實(shí)施例包括其它實(shí)施例中所包括的某些特征而不是其它特征,但是不同實(shí)施例的特征的組合意味著處于本發(fā)明的范圍之內(nèi)并且形成不同的實(shí)施例。例如,在下面的權(quán)利要求書(shū)中,所要求保護(hù)的實(shí)施例的任意之一都可以以任意的組合方式來(lái)使用。
本發(fā)明的各個(gè)部件實(shí)施例可以以硬件實(shí)現(xiàn),或者以在一個(gè)或者多個(gè)處理器上運(yùn)行的軟件模塊實(shí)現(xiàn),或者以它們的組合實(shí)現(xiàn)。本領(lǐng)域的技術(shù)人員應(yīng)當(dāng)理解,可以在實(shí)踐中使用微處理器或者數(shù)字信號(hào)處理器(DSP)來(lái)實(shí)現(xiàn)根據(jù)本發(fā)明實(shí)施例的數(shù)據(jù)寫(xiě)請(qǐng)求處理設(shè)備中的一些或者全部部件的一些或者全部功能。本發(fā)明還可以實(shí)現(xiàn)為用于執(zhí)行這里所描述的方法的一部分或者全部的設(shè)備或者裝置程序(例如,計(jì)算機(jī)程序和計(jì)算機(jī)程序產(chǎn)品)。這樣的實(shí)現(xiàn)本發(fā)明的程序可以存儲(chǔ)在計(jì)算機(jī)可讀介質(zhì)上,或者可以具有一個(gè)或者多個(gè)信號(hào)的形式。這樣的信號(hào)可以從因特網(wǎng)網(wǎng)站上下載得到,或者在載體信號(hào)上提供,或者以任何其他形式提供。
應(yīng)該注意的是上述實(shí)施例對(duì)本發(fā)明進(jìn)行說(shuō)明而不是對(duì)本發(fā)明進(jìn)行限制,并且本領(lǐng)域技術(shù)人員在不脫離所附權(quán)利要求的范圍的情況下可設(shè)計(jì)出替換實(shí)施例。在權(quán)利要求中,不應(yīng)將位于括號(hào)之間的任何參考符號(hào)構(gòu)造成對(duì)權(quán)利要求的限制。單詞“包含”不排除存在未列在權(quán)利要求中的元件或步驟。位于元件之前的單詞“一”或“一個(gè)”不排除存在多個(gè)這樣的元件。本發(fā)明可以借助于包括有若干不同元件的硬件以及借助于適當(dāng)編程的計(jì)算機(jī)來(lái)實(shí)現(xiàn)。在列舉了若干裝置的單元權(quán)利要求中,這些裝置中的若干個(gè)可以是通過(guò)同一個(gè)硬件項(xiàng)來(lái)具體體現(xiàn)。單詞第一、第二、以及第三等的使用不表示任何順序??蓪⑦@些單詞解釋為名稱。
本發(fā)明公開(kāi)了:
A1、一種數(shù)據(jù)寫(xiě)請(qǐng)求處理方法,所述方法基于調(diào)用端發(fā)送的數(shù)據(jù)寫(xiě)請(qǐng)求向存儲(chǔ)節(jié)點(diǎn)中寫(xiě)入數(shù)據(jù),其中數(shù)據(jù)寫(xiě)請(qǐng)求包含主請(qǐng)求和至少一個(gè)子請(qǐng)求,所述方法包括:
對(duì)于每一個(gè)子請(qǐng)求,調(diào)用訪問(wèn)接口從全局變量中選擇待寫(xiě)入數(shù)據(jù)的存儲(chǔ)節(jié)點(diǎn)的存儲(chǔ)節(jié)點(diǎn)地址,向所述存儲(chǔ)節(jié)點(diǎn)發(fā)送子請(qǐng)求,其中將選擇的存儲(chǔ)節(jié)點(diǎn)地址保存至子請(qǐng)求的上下文中;
從子請(qǐng)求的上下文中提取出所選擇的存儲(chǔ)節(jié)點(diǎn)地址,并保存至所述存儲(chǔ)節(jié)點(diǎn)的上下文中;
從所述存儲(chǔ)節(jié)點(diǎn)的上下文中提取出存儲(chǔ)節(jié)點(diǎn)地址,與存儲(chǔ)節(jié)點(diǎn)建立連接,將數(shù)據(jù)寫(xiě)入到相應(yīng)的存儲(chǔ)節(jié)點(diǎn)。
A2、根據(jù)A1所述的方法,其中,在發(fā)送子請(qǐng)求之前,所述方法還包括:
加載配置文件,獲取存儲(chǔ)節(jié)點(diǎn)地址列表相關(guān)的配置信息;
將存儲(chǔ)節(jié)點(diǎn)地址列表保存到所述全局變量中,生成所述全局變量的訪問(wèn)接口。
A3、根據(jù)A1或A2所述的方法,其中,在發(fā)送子請(qǐng)求之前,所述方法還包括:
獲取主請(qǐng)求的上下文;
判斷所述主請(qǐng)求的上下文是否已創(chuàng)建;
若所述主請(qǐng)求的上下文未創(chuàng)建,創(chuàng)建所述主請(qǐng)求的上下文,并將所述主請(qǐng)求的上下文與主請(qǐng)求關(guān)聯(lián)。
A4、根據(jù)A3所述的方法,其中,在發(fā)送子請(qǐng)求之前,所述方法還包括:若所述主請(qǐng)求的上下文已創(chuàng)建,判斷待寫(xiě)入數(shù)據(jù)的存儲(chǔ)節(jié)點(diǎn)是否為空;若是,則向發(fā)送數(shù)據(jù)寫(xiě)請(qǐng)求的調(diào)用端返回響應(yīng)結(jié)果;
若否,則執(zhí)行發(fā)送子請(qǐng)求的步驟。
A5、根據(jù)A1-A4中任一項(xiàng)所述的方法,其中,在將數(shù)據(jù)寫(xiě)入到相應(yīng)的存儲(chǔ)節(jié)點(diǎn)之后,所述方法還包括:
調(diào)用子請(qǐng)求完成回調(diào)函數(shù),回到主循環(huán)過(guò)程中;
在主循環(huán)過(guò)程中,調(diào)用用于處理子請(qǐng)求的處理器的入口函數(shù),利用所述用于處理子請(qǐng)求的處理器處理下一個(gè)子請(qǐng)求。
A6、根據(jù)A5所述的方法,其中,在將數(shù)據(jù)寫(xiě)入到相應(yīng)的存儲(chǔ)節(jié)點(diǎn)之后,所述方法還包括:保存所述子請(qǐng)求的上下文。
A7、根據(jù)A5所述的方法,其中,所述子請(qǐng)求的上下文中定義有狀態(tài)字段;
在將數(shù)據(jù)寫(xiě)入到相應(yīng)的存儲(chǔ)節(jié)點(diǎn)之后,所述方法還包括:更新子請(qǐng)求的上下文的狀態(tài)字段;
所述用于處理子請(qǐng)求的處理器處理下一個(gè)子請(qǐng)求具體為:所述用于處理子請(qǐng)求的處理器根據(jù)更新的狀態(tài)字段識(shí)別出數(shù)據(jù)寫(xiě)請(qǐng)求所處的階段,以便處理下一個(gè)子請(qǐng)求。
A8、根據(jù)A1-A7中任一項(xiàng)所述的方法,其中,所述方法利用部署在調(diào)用端與存儲(chǔ)節(jié)點(diǎn)之間的分布式組件實(shí)現(xiàn),所述分布式組件為反向代理服務(wù)器。
A9、根據(jù)A8所述的方法,其中,所述反向代理服務(wù)器為Nginx服務(wù)器。
B10、一種數(shù)據(jù)寫(xiě)請(qǐng)求處理裝置,所述裝置基于調(diào)用端發(fā)送的數(shù)據(jù)寫(xiě)請(qǐng)求向存儲(chǔ)節(jié)點(diǎn)中寫(xiě)入數(shù)據(jù),其中數(shù)據(jù)寫(xiě)請(qǐng)求包含主請(qǐng)求和至少一個(gè)子請(qǐng)求,所述裝置包括:用于處理子請(qǐng)求的處理器;
所述用于處理子請(qǐng)求的處理器包括:
選擇單元,適于對(duì)于每一個(gè)子請(qǐng)求,調(diào)用訪問(wèn)接口從全局變量中選擇待寫(xiě)入數(shù)據(jù)的存儲(chǔ)節(jié)點(diǎn)的存儲(chǔ)節(jié)點(diǎn)地址;
子請(qǐng)求處理單元,適于向所述存儲(chǔ)節(jié)點(diǎn)發(fā)送子請(qǐng)求,其中將選擇的存儲(chǔ)節(jié)點(diǎn)地址保存至子請(qǐng)求的上下文中;
提取單元,適于從子請(qǐng)求的上下文中提取出所選擇的存儲(chǔ)節(jié)點(diǎn)地址;
上下文寫(xiě)入單元,適于將提取出的存儲(chǔ)節(jié)點(diǎn)地址保存至所述存儲(chǔ)節(jié)點(diǎn)的上下文中;
連接單元,適于從所述存儲(chǔ)節(jié)點(diǎn)的上下文中提取出存儲(chǔ)節(jié)點(diǎn)地址,與存儲(chǔ)節(jié)點(diǎn)建立連接;
數(shù)據(jù)寫(xiě)入單元,適于將數(shù)據(jù)寫(xiě)入到相應(yīng)的存儲(chǔ)節(jié)點(diǎn)。
B11、根據(jù)B10所述的裝置,其中,所述裝置還包括:初始化模塊,適于加載配置文件,獲取存儲(chǔ)節(jié)點(diǎn)地址列表相關(guān)的配置信息;將存儲(chǔ)節(jié)點(diǎn)地址列表保存到所述全局變量中,生成所述全局變量的訪問(wèn)接口。
B12、根據(jù)B10或B11所述的裝置,其中,所述裝置還包括:用于處理主請(qǐng)求的處理器;
所述用于處理主請(qǐng)求的處理器包括:
獲取單元,適于獲取主請(qǐng)求的上下文;
第一判斷單元,適于判斷所述主請(qǐng)求的上下文是否已創(chuàng)建;
創(chuàng)建單元,適于若所述主請(qǐng)求的上下文未創(chuàng)建,創(chuàng)建所述主請(qǐng)求的上下文;
關(guān)聯(lián)單元,適于將所述主請(qǐng)求的上下文與主請(qǐng)求關(guān)聯(lián)。
B13、根據(jù)B12所述的裝置,其中,所述裝置還包括:
第二判斷模塊,適于若所述主請(qǐng)求的上下文已創(chuàng)建,判斷待寫(xiě)入數(shù)據(jù)的存儲(chǔ)節(jié)點(diǎn)是否為空;
響應(yīng)模塊,適于若待寫(xiě)入數(shù)據(jù)的存儲(chǔ)節(jié)點(diǎn)為空,向發(fā)送數(shù)據(jù)寫(xiě)請(qǐng)求的調(diào)用端返回響應(yīng)結(jié)果;
所述用于處理子請(qǐng)求的處理器具體適于在待寫(xiě)入數(shù)據(jù)的存儲(chǔ)節(jié)點(diǎn)不為空的情況下運(yùn)行。
B14、根據(jù)B10-B13中任一項(xiàng)所述的裝置,其中,所述用于處理子請(qǐng)求的處理器還包括:回調(diào)單元,適于調(diào)用子請(qǐng)求完成回調(diào)函數(shù),回到主循環(huán)過(guò)程中;
所述裝置還包括:調(diào)用模塊,適于在主循環(huán)過(guò)程中,調(diào)用用于處理子請(qǐng)求的處理器的入口函數(shù),利用所述用于處理子請(qǐng)求的處理器處理下一個(gè)子請(qǐng)求。
B15、根據(jù)B14所述的裝置,其中,所述裝置還包括:存儲(chǔ)模塊,適于保存所述子請(qǐng)求的上下文。
B16、根據(jù)B14所述的裝置,其中,所述子請(qǐng)求的上下文中定義有狀態(tài)字段;
所述用于處理子請(qǐng)求的處理器還包括:更新單元,適于更新子請(qǐng)求的上下文的狀態(tài)字段;
所述用于處理子請(qǐng)求的處理器具體適于:根據(jù)更新的狀態(tài)字段識(shí)別出數(shù)據(jù)寫(xiě)請(qǐng)求所處的階段,以便處理下一個(gè)子請(qǐng)求。
B17、根據(jù)B10-B16中任一項(xiàng)所述的裝置,其中,所述裝置利用部署在調(diào)用端與存儲(chǔ)節(jié)點(diǎn)之間的分布式組件實(shí)現(xiàn),所述分布式組件為反向代理服務(wù)器。
B18、根據(jù)B17所述的裝置,其中,所述反向代理服務(wù)器為Nginx服務(wù)器。
C19、一種分布式數(shù)據(jù)存儲(chǔ)系統(tǒng),包括:調(diào)用端、分布式組件和存儲(chǔ)節(jié)點(diǎn);其中,所述分布式組件包括B10-B18中任一項(xiàng)所述的數(shù)據(jù)寫(xiě)請(qǐng)求處理裝置。