ZooKeeper入門教程一簡(jiǎn)介與核心概念
本章是后續(xù)學(xué)習(xí)的基石,只有充分理解了分布式系統(tǒng)的概念和面臨的問(wèn)題,以及ZooKeeper內(nèi)部的概念,才能懂得ZooKeeper是如何對(duì)分布式系統(tǒng)進(jìn)行協(xié)調(diào),為后續(xù)學(xué)習(xí)打下堅(jiān)實(shí)的基礎(chǔ)。
1、ZooKeeper介紹與核心概念
1.1 簡(jiǎn)介
ZooKeeper最為主要的使用場(chǎng)景,是作為分布式系統(tǒng)的分布式協(xié)同服務(wù)。在學(xué)習(xí)zookeeper之前,先要對(duì)分布式系統(tǒng)的概念有所了解,否則你將完全不知道zookeeper在分布式系統(tǒng)中起到了什么作用,解決了什么問(wèn)題。
1.2分布式系統(tǒng)面臨的問(wèn)題
我們將分布式系統(tǒng)定義為:分布式系統(tǒng)是同時(shí)跨越多個(gè)物理主機(jī),獨(dú)立運(yùn)行的多個(gè)軟件所組成系統(tǒng)。類比一下,分布式系統(tǒng)就是一群人一起干活。人多力量大,每個(gè)服務(wù)器的算力是有限的,但是通過(guò)分布式系統(tǒng),由n個(gè)服務(wù)器組成起來(lái)的集群,算力是可以無(wú)限擴(kuò)張的。
優(yōu)點(diǎn)顯而易見,人多干活快,并且互為備份。但是缺點(diǎn)也很明顯。我們可以想象一下,以一個(gè)小研發(fā)團(tuán)隊(duì)開發(fā)軟件為例,假設(shè)我們有一個(gè)5人的項(xiàng)目組,要開始一個(gè)系統(tǒng)的開發(fā),項(xiàng)目組將面臨如下問(wèn)題:

你一定在想,以上這些問(wèn)題很簡(jiǎn)單啊,在我的日常工作中天天都在發(fā)生,并沒(méi)感覺(jué)有什么復(fù)雜。是的,這是因?yàn)槲覀內(nèi)祟惖拇竽X是個(gè)超級(jí)計(jì)算機(jī),能夠靈活應(yīng)對(duì)這些問(wèn)題,而且現(xiàn)實(shí)中信息的交換不依賴網(wǎng)絡(luò),不會(huì)因網(wǎng)絡(luò)延遲或者中斷,出現(xiàn)信息不對(duì)等。而且現(xiàn)實(shí)中對(duì)以上問(wèn)題的處理其實(shí)并不嚴(yán)謹(jǐn),從而也引發(fā)了很多問(wèn)題。
想一想,項(xiàng)目中是不是出現(xiàn)過(guò)溝通不暢造成任務(wù)分配有歧義?是否由于人員離職造成任務(wù)進(jìn)行不下去,甚至要聯(lián)系離職人員協(xié)助?是不是出現(xiàn)過(guò)任務(wù)分配不合理?類似這樣的各種問(wèn)題,肯定會(huì)發(fā)生于你的項(xiàng)目組中。
在現(xiàn)實(shí)世界,我們可以人為去協(xié)調(diào),即使出錯(cuò)了,人工去補(bǔ)錯(cuò),加加班搞定就好。但在計(jì)算機(jī)的世界,這樣做是行不通的,一切都要保證嚴(yán)謹(jǐn),以上問(wèn)題要做到盡可能不要發(fā)生。因此,分布式系統(tǒng)必須采用合理的方式解決掉以上的問(wèn)題。
實(shí)際上要想解決這些問(wèn)題并沒(méi)有那么復(fù)雜,我們僅需要做一件事就可以萬(wàn)事無(wú)憂---讓信息在項(xiàng)目組成員中同步。如果能做到信息同步,那么每個(gè)人在干什么,大家都是清楚的,干到什么程度也是清晰的,無(wú)論誰(shuí)離職也不會(huì)產(chǎn)生問(wèn)題。分配的工作,能夠及時(shí)清晰的同步給每個(gè)組員,確保每個(gè)組員收到的任務(wù)分配沒(méi)有沖突。
分布式系統(tǒng)的協(xié)調(diào)工作就是通過(guò)某種方式,讓每個(gè)節(jié)點(diǎn)的信息能夠同步和共享。這依賴于服務(wù)進(jìn)程之間的通信。通信方式有兩種:
1、通過(guò)網(wǎng)絡(luò)進(jìn)行信息共享
這就像現(xiàn)實(shí)世界,開發(fā)leader在會(huì)上把任務(wù)傳達(dá)下去,組員通過(guò)聽leader命令或者看leader的郵件知道自己要干什么。當(dāng)任務(wù)分配有變化時(shí),leader會(huì)單獨(dú)告訴組員,或者再次召開會(huì)議。信息通過(guò)人與人之間的直接溝通,完成傳遞。
2、通過(guò)共享存儲(chǔ)
這就好比開發(fā)leader按照約定的時(shí)間和路徑,把任務(wù)分配表放到了svn上,組員每天去svn上拉取最新的任務(wù)分配表,然后干活。其中svn就是共享存儲(chǔ)。更好一點(diǎn)的做法是,當(dāng)svn文件版本更新時(shí),觸發(fā)郵件通知,每個(gè)組員再去拉取最新的任務(wù)分配表。這樣做更好,因?yàn)槊看胃?,組員都能第一時(shí)間得到消息,從而讓自己手中的任務(wù)分配表永遠(yuǎn)是最新的。此種方式依賴于中央存儲(chǔ)。整個(gè)過(guò)程如下圖所示:

1.3 ZooKeeper如何解決分布式系統(tǒng)面臨的問(wèn)題
ZooKeeper對(duì)分布式系統(tǒng)的協(xié)調(diào),使用的是第二種方式,共享存儲(chǔ)。其實(shí)共享存儲(chǔ),分布式應(yīng)用也需要和存儲(chǔ)進(jìn)行網(wǎng)絡(luò)通信。網(wǎng)絡(luò)通信是分布式系統(tǒng)并發(fā)設(shè)計(jì)的基礎(chǔ)。
實(shí)際上,通過(guò)ZooKeeper實(shí)現(xiàn)分布式協(xié)同的原理,和項(xiàng)目組通過(guò)SVN同步工作任務(wù)的例子是一樣的。ZooKeeper就像是svn,存儲(chǔ)了任務(wù)的分配、完成情況等共享信息。每個(gè)分布式應(yīng)用的節(jié)點(diǎn)就是組員,訂閱這些共享信息。當(dāng)主節(jié)點(diǎn)(組leader),對(duì)某個(gè)從節(jié)點(diǎn)的分工信息作出改變時(shí),相關(guān)訂閱的從節(jié)點(diǎn)得到zookeeper的通知,取得自己最新的任務(wù)分配。完成工作后,把完成情況存儲(chǔ)到zookeeper。主節(jié)點(diǎn)訂閱了該任務(wù)的完成情況信息,所以將得到zookeeper的完工的通知。參考下圖,回味一下,是不是和前面項(xiàng)目組通過(guò)svn分配工作的例子一模一樣??jī)H僅是把svn和郵件系統(tǒng)合二為一,以ZooKeeper代替。

注:Slave節(jié)點(diǎn)要想獲取ZooKeeper的更新通知,需事先在關(guān)心的數(shù)據(jù)節(jié)點(diǎn)上設(shè)置觀察點(diǎn)。
大多數(shù)分布式系統(tǒng)中出現(xiàn)的問(wèn)題,都源于信息的共享出了問(wèn)題。如果各個(gè)節(jié)點(diǎn)間信息不能及時(shí)共享和同步,那么就會(huì)在協(xié)作過(guò)程中產(chǎn)生各種問(wèn)題。ZooKeeper解決協(xié)同問(wèn)題的關(guān)鍵,在于保證分布式系統(tǒng)信息的一致性。
通過(guò)以上章節(jié)的講解,我們應(yīng)該已經(jīng)理解分布式系統(tǒng)以及其面臨的問(wèn)題。了解了ZooKeeper通過(guò)什么樣的機(jī)制去解決這些問(wèn)題。從宏觀上對(duì)ZooKeeper已經(jīng)有了認(rèn)知,接下來(lái)我們先切入到zookeeper自身,講解zookeeper的概念,這些概念很重要,所有zookeeper的應(yīng)用都會(huì)圍繞這些概念來(lái)實(shí)現(xiàn)。
1.4 zookeeper概念介紹
ZooKeeper并不直接暴露分布式服務(wù)所需要的原語(yǔ)及原語(yǔ)的調(diào)用方法。什么是原語(yǔ)?舉個(gè)例子,比如說(shuō)分布式鎖機(jī)制是一個(gè)原語(yǔ),它會(huì)暴露出創(chuàng)建、獲取、釋放三個(gè)調(diào)用方法。ZooKeeper以類似文件系統(tǒng)的方式存儲(chǔ)數(shù)據(jù),暴漏出調(diào)用這些數(shù)據(jù)的API。讓應(yīng)用通過(guò)ZooKeeper的機(jī)制和API,自己來(lái)實(shí)現(xiàn)分布式相關(guān)原語(yǔ)。
我們?nèi)粝胱寫?yīng)用能夠通過(guò)ZooKeeper實(shí)現(xiàn)分布式協(xié)同,那么第一件事就是了解ZooKeeper的特性及相關(guān)概念,另外熟悉它給我們提供了哪些API。
1.4.1 znode
Zookeeper會(huì)保存任務(wù)的分配、完成情況,等共享信息,那么ZooKeeper是如何保存的呢?在ZooKeeper中,這些信息被保存在一個(gè)個(gè)數(shù)據(jù)節(jié)點(diǎn)上,這些節(jié)點(diǎn)被稱為znode。它采用了類似文件系統(tǒng)的層級(jí)樹狀結(jié)構(gòu)進(jìn)行管理。見下圖示例:

根節(jié)點(diǎn)/包含4個(gè)子節(jié)點(diǎn),其中三個(gè)擁有下一級(jí)節(jié)點(diǎn)。有的葉子節(jié)點(diǎn)存儲(chǔ)了信息。
節(jié)點(diǎn)上沒(méi)有存儲(chǔ)數(shù)據(jù),也有著重要的含義。比如在主從模式中,當(dāng)/master節(jié)點(diǎn)沒(méi)有數(shù)據(jù)時(shí),代表分布式應(yīng)用的主節(jié)點(diǎn)還沒(méi)有選舉出來(lái)。
znode節(jié)點(diǎn)存儲(chǔ)的數(shù)據(jù)為字節(jié)數(shù)組。存儲(chǔ)數(shù)據(jù)的格式zookeeper不做限制,也不提供解析,需要應(yīng)用自己實(shí)現(xiàn)。
實(shí)際上圖就是主從模式存儲(chǔ)數(shù)據(jù)的示例,這里先簡(jiǎn)單講解:
/master,存儲(chǔ)了當(dāng)前主節(jié)點(diǎn)的信息/workers,下面的每個(gè)子znode代表一個(gè)從節(jié)點(diǎn),子znode上存儲(chǔ)的數(shù)據(jù),如“foo.com:2181”,代表從節(jié)點(diǎn)的信息。/tasks,下面的每個(gè)子znode代表一個(gè)任務(wù),子znode上存儲(chǔ)的信息如“run cmd”,代表該內(nèi)務(wù)內(nèi)容/assign,下面每個(gè)子znode代表一個(gè)從節(jié)點(diǎn)的任務(wù)集合。如/assign/worker-1,代表worker-1這個(gè)從節(jié)點(diǎn)的任務(wù)集合。/assign/worker-1下的每個(gè)子znode代表分配給worker-1的一個(gè)任務(wù)。
持久節(jié)點(diǎn)(persistent)和臨時(shí)節(jié)點(diǎn)(ephemeral)
持久節(jié)點(diǎn)只能通過(guò)delete刪除。臨時(shí)節(jié)點(diǎn)在創(chuàng)建該節(jié)點(diǎn)的客戶端崩潰或關(guān)閉時(shí),自動(dòng)被刪除。
前面例子中的/master應(yīng)該使用臨時(shí)節(jié)點(diǎn),這樣當(dāng)主節(jié)點(diǎn)失效或者退出時(shí),該znode被刪除,其他節(jié)點(diǎn)知道主節(jié)點(diǎn)崩潰了,開始進(jìn)行選舉的邏輯。另外/works/worker-1也應(yīng)該是臨時(shí)節(jié)點(diǎn),在此從節(jié)點(diǎn)失效的時(shí)候,該臨時(shí)節(jié)點(diǎn)自動(dòng)刪除。
在目前的版本,由于臨時(shí)znode會(huì)因?yàn)閯?chuàng)建者會(huì)話過(guò)期被刪除,所以不允許臨時(shí)節(jié)點(diǎn)擁有子節(jié)點(diǎn)。
有序節(jié)點(diǎn)
znode可以被設(shè)置為有序(sequential)節(jié)點(diǎn)。有序znode節(jié)點(diǎn)被分配唯一一個(gè)單調(diào)遞增的證書。如果創(chuàng)建了個(gè)一有序節(jié)點(diǎn)為/workers/worker-,zookeeper會(huì)自動(dòng)分配一個(gè)序號(hào)1,追加在名字后面,znode名稱為/workers/worker-1。通過(guò)這種方式,可以創(chuàng)建唯一名稱znode,并且可以直觀的看到創(chuàng)建的順序。
znode支持的操作及暴露的API:
create /path data
創(chuàng)建一個(gè)名為/path的znode,數(shù)據(jù)為data。
delete /path
刪除名為/path的znode。
exists /path
檢查是否存在名為/path的znode
setData /path data
設(shè)置名為/path的znode的數(shù)據(jù)為data
getData /path
返回名為/path的znode的數(shù)據(jù)
getChildren /path
返回所有/path節(jié)點(diǎn)的所有子節(jié)點(diǎn)列表
1.4.2 觀察與通知
分布式應(yīng)用需要及時(shí)知道zookeeper中znode的變化,從而了解到分布式應(yīng)用整體的狀況,如果采用輪詢方式,代價(jià)太大,絕大多數(shù)查詢都是無(wú)效的。因此,zookeeper采用了通知的機(jī)制。客戶端向zookeeper請(qǐng)求,在特定的znode設(shè)置觀察點(diǎn)(watch)。當(dāng)該znode發(fā)生變化時(shí),會(huì)觸發(fā)zookeeper的通知,客戶端收到通知后進(jìn)行業(yè)務(wù)處理。觀察點(diǎn)觸發(fā)后立即失效。所以一旦觀察點(diǎn)觸發(fā),需要再次設(shè)置新的觀察點(diǎn)。
我們使用Zookeeper不能期望能夠監(jiān)控到節(jié)點(diǎn)每次的變化。思考如下場(chǎng)景:
- 1、客戶端C1設(shè)置觀察點(diǎn)在/tasks
- 2、觀察點(diǎn)觸發(fā),C1處理自己的邏輯
- 3、C1設(shè)置新的觀察點(diǎn)前,C2更新了/tasks
- 4、C1處理完邏輯,再次設(shè)置了觀察點(diǎn)。
此時(shí)C1不會(huì)得到第三步的通知,因此錯(cuò)過(guò)了C2更新/tasks這次操作。要想不錯(cuò)過(guò)這次更新,C1需要在設(shè)置監(jiān)視點(diǎn)前讀取/tasks的數(shù)據(jù),進(jìn)行對(duì)比,發(fā)現(xiàn)更新。
再如下面的場(chǎng)景:
- 1、客戶端C1設(shè)置觀察點(diǎn)在/tasks
- 2、/tasks上發(fā)生了連續(xù)兩次更新
- 3、C1在得到第一次更新的通知后就讀取了/tasks的數(shù)據(jù)
- 4、此時(shí)第二次更新也已經(jīng)發(fā)生,C1用第一次的通知,讀取到兩次更新后的數(shù)據(jù)
此時(shí)C1雖然錯(cuò)過(guò)了第二次通知,但是C1最終還是讀取到了最新的數(shù)據(jù)。
因此Zookeeper只能保證最終的一致性,而無(wú)法保證強(qiáng)一致性。
zookeeper可以定義不同的觀察類型。例如觀察znode數(shù)據(jù)變化,觀察znode子節(jié)點(diǎn)變化,觀察znode創(chuàng)建或者刪除。
1.4.3 版本
每個(gè)znode都有版本號(hào),隨著每次數(shù)據(jù)變化自增。setData和delete,以版本號(hào)作為參數(shù),當(dāng)傳入的版本號(hào)和服務(wù)器上不一致時(shí),調(diào)用失敗。當(dāng)多個(gè)zookeeper客戶端同時(shí)對(duì)一個(gè)znode操作時(shí),版本將會(huì)起到作用,假設(shè)c1,c2同時(shí)往一個(gè)znode寫數(shù)據(jù),c1先寫完后版本從1升為2,但是c2寫的時(shí)候攜帶版本號(hào)1,c2會(huì)寫入失敗。
1.4.4 法定人數(shù)
zookeeper服務(wù)器運(yùn)行于兩種模式:獨(dú)立模式和仲裁模式(集群)。仲裁模式下,會(huì)復(fù)制所有服務(wù)器的數(shù)據(jù)樹。但如果讓客戶端等待所有復(fù)制完成,延遲太高。這里引入法定人數(shù)概念,指為了使zookeeper集群正常工作,必須有效運(yùn)行的服務(wù)器數(shù)量。同時(shí)也是服務(wù)器通知客戶端保存成功前,必須保存數(shù)據(jù)的服務(wù)器最小數(shù)。例如我們有一個(gè)5臺(tái)服務(wù)器的zookeeper集群,法定人數(shù)為3,只要任何3個(gè)服務(wù)器保存了數(shù)據(jù),客戶端就會(huì)收到確認(rèn)。只要有3臺(tái)服務(wù)器存活,整個(gè)zookeeper集群就是可用的。
下圖展示了客戶端提交請(qǐng)求到收到回復(fù)的過(guò)程:

法定人數(shù)需要大于服務(wù)器數(shù)量的一半。也稱為多數(shù)原則。舉個(gè)例子說(shuō)明,假如集群有5臺(tái)服務(wù)器,法定人數(shù)為2,那么有2臺(tái)服務(wù)器參與復(fù)制即可,若這2臺(tái)server剛剛復(fù)制完/z這個(gè)znode,就掛掉了。此時(shí)剩下了3臺(tái)server,大于法定人數(shù)2,所以zookeeper認(rèn)為集群正常,但這三臺(tái)服務(wù)器是無(wú)法發(fā)現(xiàn)/z這個(gè)znode的。如果法定人數(shù)大于服務(wù)器數(shù)量一半,那么法定人數(shù)復(fù)制完成,就可以確保集群存活時(shí),至少有一臺(tái)服務(wù)器有最新的znode,否則集群認(rèn)為自己已經(jīng)崩潰。
下面兩個(gè)例子闡明了,為何要遵循多數(shù)原則。
下圖展示了5臺(tái)server,法定人數(shù)為3,在確保zookeeper集群存活的前提下,最壞的情況掛了2臺(tái)server(剩余及器數(shù)量3>=法定人數(shù)3),zookeeper是如何能確保數(shù)據(jù)完備,集群繼續(xù)工作的。

接下來(lái)兩張圖展示了5臺(tái)server,未遵循多數(shù)原則,法定人數(shù)設(shè)為2。同樣掛了兩臺(tái)server時(shí),為什么zookeeper集群會(huì)出問(wèn)題。
首先,客戶端發(fā)起請(qǐng)求,2個(gè)server復(fù)制數(shù)據(jù)后即返回客戶端接收成功。

就在此刻,很不幸,在繼續(xù)同步更新給其他節(jié)點(diǎn)前,剛剛兩個(gè)復(fù)制了數(shù)據(jù)的節(jié)點(diǎn)掛了。
此時(shí)會(huì)怎樣呢?如下圖:

可以看到創(chuàng)建/z的操作在zookeeper集群中丟失了。
相信通過(guò)以上講解,你已經(jīng)能夠理解為什么法定人數(shù)一定要多于一半服務(wù)器的數(shù)量。
此外,我們要盡量選用奇數(shù)個(gè)服務(wù)器,這樣集群能容忍崩潰服務(wù)器占比更大,性價(jià)比更高。例如4臺(tái)服務(wù)器的集群,法定人數(shù)最少為3,那么只能允許1臺(tái)服務(wù)器崩潰,也就是僅允許25%的機(jī)器崩潰。而5臺(tái)服務(wù)器的集群,法定人數(shù)最少也是3,但是此時(shí)允許2臺(tái)服務(wù)器崩潰。換句話講,40%的機(jī)器崩潰后還能工作。
仲裁模式下,負(fù)載均衡通過(guò)客戶端隨機(jī)選擇連接串中的某個(gè)服務(wù)器來(lái)實(shí)現(xiàn)。
1.4.5 會(huì)話
客戶端對(duì)zookeeper集群發(fā)送任何請(qǐng)求前,需要和zookeeper集群建立會(huì)話??蛻舳颂峤唤ozookeeper的所有操作均關(guān)聯(lián)在一個(gè)會(huì)話上。當(dāng)一個(gè)會(huì)話因某種原因終止時(shí),會(huì)話期間創(chuàng)建的臨時(shí)節(jié)點(diǎn)將會(huì)消失。而當(dāng)當(dāng)前服務(wù)器的問(wèn)題,無(wú)法繼續(xù)通信時(shí),會(huì)話將被透明的轉(zhuǎn)移到另外一臺(tái)zookeeper集群的服務(wù)器上。
會(huì)話提供了順序保障。同一個(gè)會(huì)話中的請(qǐng)求以FIFO順序執(zhí)行。并發(fā)會(huì)話的FIFO順序無(wú)法保證。
1.4.6 會(huì)話狀態(tài)和生命周期
會(huì)話狀態(tài)有:
connecting、connected、closed、not_connected
創(chuàng)建會(huì)話時(shí),需要設(shè)置會(huì)話超時(shí)這個(gè)重要的參數(shù)。如果經(jīng)過(guò)時(shí)間t后服務(wù)接受不到這個(gè)會(huì)話的任何消息,服務(wù)就會(huì)聲明會(huì)話過(guò)期??蛻舳藗?cè),t/3時(shí)間未收到任何消息,客戶端向服務(wù)器發(fā)送心跳消息,2t/3時(shí)間后,客戶端開始尋找其他服務(wù)器。此時(shí)他有t/3的時(shí)間去尋找,找不到的話,會(huì)話失效。
重連服務(wù)器時(shí),只有更新大于客戶端的服務(wù)器才能被連接,以免連接到落后的服務(wù)器。zookeeper中通過(guò)更新建立的順序,分配事務(wù)標(biāo)識(shí)符。只有服務(wù)器的事物標(biāo)識(shí)符大于客戶端攜帶的標(biāo)識(shí)符時(shí),才可連接。
回顧總結(jié)
本章首先介紹了分布式系統(tǒng)及分布式系統(tǒng)面臨的問(wèn)題,隨后介紹了zookeeper是以何機(jī)制來(lái)解決這些問(wèn)題的。最后介紹了zookeeper中的重要概念,在開始后續(xù)學(xué)習(xí)前,一定要確保自己理解了這些重要的概念,本章知識(shí)是后面章節(jié)學(xué)習(xí)的重要基石,希望大家以后多多支持腳本之家!
相關(guān)文章
spring自定義注解實(shí)現(xiàn)攔截器的實(shí)現(xiàn)方法
本篇文章主要介紹了spring自定義注解實(shí)現(xiàn)攔截器的實(shí)現(xiàn)方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-08-08
Java實(shí)現(xiàn)對(duì)稱加密DES和AES的示例代碼
這篇文章主要介紹了如何使用Java實(shí)現(xiàn)采用對(duì)稱密碼算法的應(yīng)用軟件,所用算法包括DES算法和AES算法,文中的示例代碼講解詳細(xì),感興趣的可以了解一下2023-04-04
Java代碼為例講解堆的性質(zhì)和基本操作以及排序方法
堆數(shù)據(jù)結(jié)構(gòu)可以看作一顆完全二叉樹,因而又被成為二叉堆,這里我們以Java代碼為例講解堆的性質(zhì)和基本操作以及排序方法,需要的朋友可以參考下2016-06-06
java中實(shí)現(xiàn)視頻處理以及播放功能代碼詳解
這篇文章主要給大家介紹了關(guān)于java中實(shí)現(xiàn)視頻處理以及播放功能的相關(guān)資料,最近要實(shí)現(xiàn)一套音視頻播放程序,所以這里給大家總結(jié)下,需要的朋友可以參考下2023-09-09
詳解springboot設(shè)置cors跨域請(qǐng)求的兩種方式
這篇文章主要介紹了詳解springboot設(shè)置cors跨域請(qǐng)求的兩種方式,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-11-11
SpringBoot多級(jí)緩存實(shí)現(xiàn)方案總結(jié)
所謂多級(jí)緩存,是指在整個(gè)系統(tǒng)架構(gòu)的不同系統(tǒng)層面進(jìn)行數(shù)據(jù)緩存,以提升訪問(wèn)速度,多級(jí)緩存就是為了解決項(xiàng)目服務(wù)中單一緩存使用不足的缺點(diǎn),本文我們將給大家總結(jié)了SpringBoot多級(jí)緩存實(shí)現(xiàn)方案,需要的朋友可以參考下2023-08-08
詳解Java對(duì)象創(chuàng)建的過(guò)程及內(nèi)存布局
今天給大家?guī)?lái)的文章是Java對(duì)象創(chuàng)建的過(guò)程及內(nèi)存布局,文中有非常詳細(xì)的圖文示例及介紹,需要的朋友可以參考下2021-06-06

