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