您好,登錄后才能下訂單哦!
這篇文章主要為大家展示了“Raft一致性算法有哪些”,內(nèi)容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“Raft一致性算法有哪些”這篇文章吧。
Raft是一種用來管理日志復(fù)制的一致性算法。一致性算法允許一組機(jī)器像一個(gè)整體一樣工作,即使其中的一些機(jī)器出了錯(cuò)誤也能正常工作。
復(fù)制狀態(tài)機(jī)(State Machine Replication):通過復(fù)制服務(wù)副本,并和副本一起來協(xié)調(diào)客戶端的交互,來實(shí)現(xiàn)容錯(cuò)服務(wù)。Raft復(fù)制狀態(tài)機(jī)是通過復(fù)制日志來實(shí)現(xiàn)的,每一臺服務(wù)器保存著一份日志。
Raft實(shí)現(xiàn)一致性是首先選擇一個(gè)確定的leader,然后leader負(fù)責(zé)管理日志復(fù)制。leader接受來自客戶端的請求并追加到本地日志,然后把日志復(fù)制到其它的機(jī)器并告訴其它機(jī)器什么時(shí)候可以安全的將日志應(yīng)用到狀態(tài)機(jī)。集群存在一個(gè)leader的好處可以簡化日志復(fù)制的管理。例如:leader可以決定日志的追加,而不需要經(jīng)其它機(jī)器的同意。整個(gè)集群的數(shù)據(jù)流向也是從leader流向其它機(jī)器。如果leader宕機(jī)或者網(wǎng)絡(luò)斷開,其它的機(jī)器可以重新選舉一個(gè)新的leader。
Raft一致性問題分解為3個(gè)相對獨(dú)立的子問題
Leader election:當(dāng)一個(gè)leader宕機(jī)后,一個(gè)新的leader必須被選舉。
Log replication:leader必須響應(yīng)客戶端的請求,并把日志復(fù)制到整個(gè)集群來保證其它機(jī)器的日志和自己的相同。
Safety:狀態(tài)機(jī)的安全是Raft優(yōu)先保證的。如果任意一臺機(jī)器將一條特定的日志應(yīng)用到自己的狀態(tài)機(jī),那么其他的機(jī)器就不能應(yīng)用一條不同的日志到自己的狀態(tài)機(jī)。解決這個(gè)問題的方案就是在選舉是增加額外的規(guī)則約束。
強(qiáng)領(lǐng)導(dǎo)者(Strong Leader):日志條目只從領(lǐng)導(dǎo)者發(fā)送向其他服務(wù)器。
領(lǐng)導(dǎo)選取(Leader Selection):Raft使用了隨機(jī)定時(shí)器來選擇leader。
成員變化(Membership Change):Raft使用了一種聯(lián)合一致性的方法,使得集群中的機(jī)器發(fā)生變更的時(shí)候,整個(gè)集群也可以正常的工作。聯(lián)合一致性配置是兩個(gè)不同配置的大多數(shù)機(jī)器的重疊。
所有機(jī)器需要持久化的狀態(tài)(在RPC響應(yīng)之前,需要更新穩(wěn)定存儲介質(zhì))
currentTerm 服務(wù)器存儲的最新任期號從0開始遞增
votedFor 在當(dāng)前任期內(nèi)收到選票的候選人id如果沒有就為null
log[] 日志條目;每個(gè)條目包含狀態(tài)機(jī)的要執(zhí)行命令和從領(lǐng)導(dǎo)人處收到時(shí)的任期號
所有機(jī)器的可變狀態(tài)
commitIndex 將被提交的日志記錄的索引從0開始遞增
lastApplied 已經(jīng)被提交到狀態(tài)機(jī)的最后一個(gè)日志的索引從0開始遞增
leader的可變狀態(tài)(每次選舉后重新初始化)
nextIndex[] 每臺機(jī)器在數(shù)組占據(jù)一個(gè)元素,元素的值為下條發(fā)送到該機(jī)器的日志索引(初始值為 leader最新一條日志的索引+1)
matchIndex[] 每臺機(jī)器在數(shù)組中占據(jù)一個(gè)元素,元素的記錄將要復(fù)制給該機(jī)器日志的索引的從0開始遞增
被leader用來復(fù)制日志;同時(shí)也被用作心跳。
Arguments:
term leader任期
leaderId 用來follower重定向到leader
prevLogIndex 前繼日志記錄的索引
prevLogTerm 前繼日志的任期
entries[] 存儲日志記錄
leaderCommit leader的commitIndex
Results:
term 當(dāng)前的任期號,用于領(lǐng)導(dǎo)人更新自己的任期號
success 如果follower包含索引為prevLogIndex和任期為prevLogItem的日志
接受者的實(shí)現(xiàn)
1.如果leader的任期小于自己的任期返回false。
2.如果自己不存在索引、任期和 prevLogIndex、prevLogItem匹配的日志返回false。
3.如果存在一條日志索引和prevLogIndex相等,但是任期和prevLogItem不相同的日志,需要刪除這條日志及所有后繼日志。
4.如果leader復(fù)制的日志本地沒有,則直接追加存儲。
5.如果leaderCommit>commitIndex,設(shè)置本地commitIndex為leaderCommit和最新日志索引中較小的一個(gè)。
被候選者用來收集選票
Arguments:
term 候選者的任期
candidateId 候選者編號
lastLogIndex 候選者最后一條日志記錄的索引
lastLogTerm 候選者最后一條日志記錄的索引的任期
Results:
term 當(dāng)前任期,候選者用來更新自己
voteGranted 如果候選者當(dāng)選則為true
接受者的實(shí)現(xiàn):
1.如果leader的任期小于自己的任期返回false
2.如果本地voteFor為空,候選者日志和本地日志相同,則投票給該候選者
所有機(jī)器
1.如果commitIndex > lastApplied:增加lastApplied,并將日志log[lastApplied]應(yīng)用到狀態(tài)機(jī)
2.如果RPC的請求或者響應(yīng)中包含一個(gè)term T大于currentTerm,則currentTerm賦值為T,并切換狀態(tài)為追隨者(Follower)
追隨者/參與者(followers)
1.響應(yīng)來自候選者或者leader的請求
2.如果在超過選取領(lǐng)導(dǎo)人時(shí)間之前沒有收到來自當(dāng)前領(lǐng)導(dǎo)人的AppendEntries RPC或者沒有收到候選人的投票請求,則自己轉(zhuǎn)換狀態(tài)為候選人
候選人(candidate)
1.一旦變?yōu)楹蜻x者,則開始啟動選舉
1.1 currentTerm自增
1.2 選舉自己
1.3 重置選舉定時(shí)器
1.4 并行發(fā)送選舉請求到其他所有機(jī)器
2.如果收到集群大多數(shù)機(jī)器的選票,則稱為新的leader
3.如果收到了來自新領(lǐng)導(dǎo)人的AppendEntries RPC(heartbeat)轉(zhuǎn)換為追隨者
4.如果選舉超時(shí)開始新一輪的選舉
領(lǐng)導(dǎo)者(leaders):
1.一旦成為領(lǐng)導(dǎo)人:向其他所有服務(wù)器發(fā)送空的AppendEntries RPC(heartbeat); 在空閑時(shí)間重復(fù)發(fā)送以防止選舉超時(shí)
2.如果接受到來自客戶端的請求,追加日志記錄到本地日志,如果成功應(yīng)用日志記錄到狀態(tài)機(jī)則回應(yīng)客戶端。
3.如果某個(gè)參與者的最新日志索引大于等于本地存儲該參與者的最新日志索引:給該參與者發(fā)送包含從 nextIndex開始的日志追加請求。
3.1 如果成功,更新該參與者的 nextIndex和matchIndex。
3.2 如果由于日志不一致而失敗,減少nextIndex并重試。
4.如果存在N > commitIndex(本地待提交日志的索引),majority(matchIndex[i]>= N)(如果參與者大多數(shù)的最新日志的索引大于 N),并且這些參與者索引為N的日志的任期也等于leader的當(dāng)前任期:commitIndex=N(leader的待提交的日志索引設(shè)置為N)
Raft 一致性算法的總結(jié)
選舉安全原則(Election Safety) 在一個(gè)給定的任期最多只可以選舉出一個(gè)leader。
領(lǐng)導(dǎo)人只增加原則(Leader Append-Only)對于一個(gè)leader它永遠(yuǎn)不會重寫和刪除日志中的日志記錄,它只會追加日志記錄。
日志匹配原則(Log Matching) 如果兩個(gè)日志文件中存在相同索引和任期的日志記錄那么兩個(gè)日志文件所有的日志記錄在給定索引情況下是相同的。
領(lǐng)導(dǎo)人完全原則(Leader Completeness) 如果一條日志在一個(gè)給定的任期已經(jīng)提交,那么這條日志將會出現(xiàn)在所有任期大于給定任期的leader的日志中。
狀態(tài)機(jī)安全原則(State Machine Safety)如果一個(gè)server已經(jīng)將給定索引的日志應(yīng)用到狀態(tài)機(jī),別的server將不能應(yīng)用一個(gè)相同索引但內(nèi)容不同的日志記錄到自己的狀態(tài)機(jī)。
任意時(shí)刻,一臺server會處在三種狀態(tài)中的一種:leader、follower和candidate。
正常情況下,集群中包含一個(gè)leader和參與者。集群中的參與者是被動的,它們不會主動解決問題而是被動的響應(yīng)leader或者參與者的請求。集群中l(wèi)eader負(fù)責(zé)處理所有的客戶端請求,如果一個(gè)客戶端的請求連接到了參與者,這個(gè)參與者會將請求重定向到leader。候選者是在選舉中可能成為leader的狀態(tài)。
Raft將時(shí)間分為任意長度的間隔,每個(gè)間隔是一個(gè)任期。每個(gè)任期會由一個(gè)連續(xù)的整數(shù)進(jìn)行表示。每個(gè)任期都是從選舉開始的,在這個(gè)階段會有一個(gè)或者多個(gè)候選者參與競選。一旦某個(gè)候選者在選舉中勝出,這個(gè)任期剩下的時(shí)間將有這個(gè)候選者作為leader。
一些特殊的情況下,一次選舉可能出現(xiàn)選舉分裂的情況。選舉分裂的情況下,當(dāng)前任期將不會選舉出leader。緊接著一個(gè)新的任期將會啟動重新進(jìn)行選舉。Raft通過上面的過程保證每個(gè)任期只會選舉出至多一個(gè)leader。
當(dāng)servers進(jìn)行通訊的時(shí)候,也會交換當(dāng)前的任期。如果一個(gè) server 存儲的任期小于其他機(jī)器存儲的任期,那么它將更新自己的任期到其它機(jī)器存儲的最大任期。如果是一個(gè)候選者或者leader發(fā)現(xiàn)自己的任期已經(jīng)過期,它們會轉(zhuǎn)變到參與者的狀態(tài)。如果一個(gè)server接受到一個(gè)請求,這個(gè)請求中的任期是過時(shí)的,它將直接拒絕該請求。
Raft使用心跳機(jī)制來觸發(fā)選主的過程。當(dāng)servers啟動的時(shí)候,都是作為參與者。如果一個(gè)參與者收到來自leader或者候選者的合法請求,它將保持在參與者的狀態(tài)。leader會發(fā)送心跳到其它的server來授權(quán)延長自己的任期。如果一個(gè)參與者的選舉定時(shí)器超時(shí)的時(shí)候還沒有收到任何請求,它可以假設(shè)整個(gè)集群沒有可用的leader或者候選者,然后發(fā)起新的選舉。
一次選舉開始時(shí),參與者增加自己本地存儲的當(dāng)前任期然后轉(zhuǎn)變?yōu)楹蜻x者狀態(tài)。這個(gè)候選者先選舉自己,并行的給集群中的其它機(jī)器發(fā)送 RequestVote RPCs。
候選者將會一直保持候選狀態(tài)直到下面三件事情中的任意一件發(fā)生:(a):候選者本次選舉勝出(b):另外一臺機(jī)器確認(rèn)自己是leader(c):僵持一段時(shí)候沒有人勝出。
一個(gè)候選者如果接受到集群中大多數(shù)機(jī)器在同一個(gè)任期的選票,么它將勝出成為leader。每臺機(jī)器在一個(gè)任期只能投票給一個(gè)候選者,按照先到先服務(wù)的原則。大多數(shù)投票勝出規(guī)則可以保證在一個(gè)特定的任期至多選出一個(gè)leader。一旦一個(gè)候選者勝出將成為集群的leader,它將會并行的給集群的其它機(jī)器發(fā)送心跳來宣示自己勝出,并阻止進(jìn)行新的選舉。
在等待選票的過程中,一個(gè)候選者可能接受到來自其它server的請求,該請求聲明自己已經(jīng)成為 leader。如果請求中的leader的任期大于候選者本地存儲的任期,那么當(dāng)前候選者認(rèn)為這個(gè)leader 是合法的并轉(zhuǎn)變?yōu)閰⑴c者狀態(tài)。如果請求中l(wèi)eader的任期小于當(dāng)前候選者本地存儲的任期,那么候選將拒絕這個(gè)請求并保持在候選者狀態(tài)。
第三種可能是是整個(gè)集群的所有候選者都沒有勝出。如果集群中所有的參與者同一時(shí)刻轉(zhuǎn)變?yōu)楹蜻x者,
由于每個(gè)機(jī)器只能投票給一個(gè)候選者,這種情況新會很容易發(fā)生選舉分裂即沒有一個(gè)候選者獲得半數(shù)以上選票。當(dāng)這種情況發(fā)生,所有的候選者的選舉定時(shí)器將會超時(shí),它們增加自己本地存儲的任期并啟動新一輪的選舉。從上面可以看出如果沒有額外的規(guī)則約束,選舉分裂的情況將極易發(fā)生。
Raft通過隨機(jī)選舉定時(shí)器來阻止選舉分裂的發(fā)生,即使選舉分裂發(fā)生也可以很快的被解決。選舉超時(shí)將在 [150,300]ms之間隨機(jī)生成,這樣就大概率保證集群中會有一個(gè)機(jī)器會先超時(shí),而避免所有機(jī)器同時(shí)超時(shí)從而降低選舉分裂情況發(fā)生的概率。如果首先超時(shí)的機(jī)器將會首先轉(zhuǎn)變?yōu)楹蜻x者,它將會大概率的選舉勝出成為leader,然后發(fā)送心跳續(xù)阻止其它機(jī)器定時(shí)器超時(shí)。
一旦一個(gè)候選者成為leader,它將開始處理客戶端的請求。客戶端的每個(gè)請求包含了一條需要執(zhí)行到狀態(tài)機(jī)的命令。leader將命令追加到自己的日志記錄,同時(shí)并發(fā)AppendEntries RPCs請求來進(jìn)行日志復(fù)制。當(dāng)日志安全的復(fù)制之后,leader 將日志應(yīng)用到自己的狀態(tài)機(jī)并將結(jié)果返回給客戶端。如果集群中有參與者宕機(jī)、處理速度慢、網(wǎng)絡(luò)丟包等情況發(fā)生,leader將重試AppendEntries RPCs請求直到日志被安全的復(fù)制。
leader來決定將一條日志應(yīng)用到狀態(tài)機(jī)的安全時(shí)機(jī)。這樣的一條日志被稱為committed。Raft來保證日志的持久化并且所有已提交的日志將會都會被應(yīng)用到狀態(tài)機(jī)。一旦leader將一條日志成功的復(fù)制到集群的大多數(shù)機(jī)器,那么這條日志就是已提交狀態(tài)。如果當(dāng)前日志記錄已提交,那么由前任leader或者當(dāng)前l(fā)eader創(chuàng)建的前繼日志記錄都會被提交。leader維護(hù)了即將被提交的日志記錄的索引,并把這個(gè)索引放在未來的AppendEntries RPCs請求中。當(dāng)參與者從請求獲知已提交的索引,它會將本地該索引的日志應(yīng)用到狀態(tài)機(jī)。
如果兩個(gè)日志的兩條日志記錄有相同的索引和任期,那么這兩條日志記錄中的命令必然也是相同的。
如果兩個(gè)日志的兩條日志記錄有相同的索引和任期,那么這兩個(gè)日志中的前繼日志記錄也是相同的。
在一個(gè)給定的任期,leader創(chuàng)建的日志索引是遞增不重復(fù)的,一旦日志某條日志創(chuàng)建后是不會改變它在日志中位置。上面的事實(shí)保證了第一個(gè)性質(zhì)的成立。每次當(dāng)leader發(fā)送AppendEntries RPCs請求的時(shí)候,請求中會包含當(dāng)前正在復(fù)制的日志記錄的直接前繼的任期和索引,如果參與者在自己的日志中沒有發(fā)現(xiàn)有相同任期和索引的日志記錄,它將直接拒絕請求。上面描述的一致性檢測保證第二個(gè)性質(zhì)的成立。一致性檢測的步驟如下:初始化時(shí)候是滿足Log Matching Property的;當(dāng)有追加日志的時(shí)候進(jìn)行一次一致性檢測來保護(hù)Log Matching Property。這樣當(dāng)leader接受到返回成功的 AppendEntries RPCs請求時(shí),說明了參與者與自己的日志是相同的。
正常情況下,leader 和參與者的日志都是相同的,日志一致性檢測也不失敗。當(dāng)leader崩潰的時(shí)候就會導(dǎo)致日志的不一致,例如舊的leader沒有將自己的日志記錄安全的復(fù)制到其它機(jī)器。這些不一致可能聚合多個(gè)leader和參與者的崩潰。一個(gè)參與者可能缺失了leader有的日志記錄,它也可能多出了leader沒有的日志,或者上面的兩種情況同時(shí)發(fā)生。缺失或多余的日志可能存在在多個(gè)任期。
Raft 是通過強(qiáng)制參與者只能復(fù)制leader的日志來解決不一致。這就意味者參與者的日志和leader的日志發(fā)生沖突的時(shí)候,參與者的日志將會重寫或者刪除。在額外附加的約束下上面的過程是安全的。
如果一致性檢測失敗后,為了保證參與者和自己的日志一致,leader需要先確認(rèn)參與者和自己一致的最后一條日志記錄。然后通知參與者刪除這條日志記錄后面的日志,并將這條日志記錄之后的日志復(fù)制給參與者。leader為每個(gè)參與者維護(hù)了nextIndex,這個(gè)索引記錄了leader將復(fù)制給該參與者的日志索引。當(dāng)一個(gè)leader選舉生效后,它將初始化nextIndex為它自己日志記錄中最后一條日志記錄的索引。如果leader的日志和參與者的日志不一致那么下一輪的AppendEntries RPCs進(jìn)行AppendEntries一致性檢測的時(shí)候就會發(fā)現(xiàn)。如果檢測發(fā)生不一致,leader將會減少nextIndex并重試。經(jīng)過多次重試leader就會確定參與者和自己一致的日志索引,然后通知參與者刪除后面不一致的日志,然后復(fù)制自己的日志給參與者。經(jīng)過上面的過程leader和參與者的一致就可以恢復(fù)一致。
上面過程中每次nextIndex減少1進(jìn)行重試效率是存在問題的,但是也是可以優(yōu)化的。一旦參與者進(jìn)行日志一致性檢測發(fā)現(xiàn)不一致之后,在響應(yīng)leader請求中包含自己在這個(gè)任期存儲的第一條日志。這樣 leader接受到響應(yīng)后,就可以直接跳過所有沖突的日志(其中可能包含了一致的日志)。這樣就可以減少尋找一致點(diǎn)的過程。但是在實(shí)際中我們懷疑這種優(yōu)化的必要性,因?yàn)槭“l(fā)生的概率本來就很低,也不會同時(shí)存在大量不一致的日志記錄。
使用上面的機(jī)制,一個(gè)leader生效的時(shí)候就不需要進(jìn)行額外的操作來恢復(fù)日志的一致性。它只需按照正常的流程,日志的不一致經(jīng)過多次AppendEntries RPCs一致性檢測后會自動收斂。leader也不需要重寫和刪除本地日志。
Raft可以在集群只有半數(shù)以上存活的情況下接受、復(fù)制和應(yīng)用新的日志記錄;正常情況下只需要一輪 RPCs可以將日志記錄復(fù)制到集群的大多數(shù);單個(gè)速度慢的參與者不會影響整個(gè)集群的性能。
上面描述了Raft的選主和日志復(fù)制。但是目前所描述的機(jī)制還不能安全的保證日志是按照相同順序被應(yīng)用到狀態(tài)機(jī)。例如:在leader提交了若干條日志后,某個(gè)參與者宕機(jī)并被選為新的leader。新的leader重寫其它機(jī)器的日志,結(jié)果導(dǎo)致不同的狀態(tài)機(jī)有不同的命令序。我們通過添加額外約束控制某些機(jī)器能被選舉為leader來完善Raft算法。這個(gè)約束保證當(dāng)選的leader包含了前任所有提交的日志。 通過約束我們可以精準(zhǔn)的控制日志的提交。
Raft使用的方法是每個(gè)當(dāng)選的leader必須之前所提交的所有日志,這種方法帶來的好處是集群中數(shù)據(jù)的流向只能是從leader到參與者,leader永遠(yuǎn)僅需要追加即可。
Raft 使用選舉過程來保證一個(gè)候選者必須包含有所有已提交的日志才能勝出。候選者為了勝出必須聯(lián)系集群中的大多數(shù)機(jī)器,這就意味著每條日志至少出現(xiàn)在機(jī)群中的某一臺機(jī)器上。如果候選者的日志如果比集群其它任意一臺機(jī)器的日志更新(下面精確定義“更新”),那么它將包含所有已提交的日志。RequestVote RPCs來實(shí)現(xiàn)這個(gè)約束:請求中包含了 leader 的日志信息,如果投票者的日志比候選者的日志更新,那么它就拒絕投票。
兩個(gè)日志文件誰的日志更新是通過比較日志中最后一條日志記錄的任期和索引。如果兩個(gè)日志文件的最后一條日志的任期不相同,誰的任期更大誰的的日志將更新。如果兩條日志記錄的任期相同,那么誰的索引越大,誰的日志將更新。
如果當(dāng)前任期的一條日志已經(jīng)被復(fù)制到集群中的大多數(shù),那么leader可以確定這條已經(jīng)已經(jīng)處于提交狀態(tài)。如果上任leader在提交日志之前宕機(jī),下一任leader將嘗試完成日志的復(fù)制。然而,盡管上一任期的某條日志已經(jīng)被復(fù)制到了大多數(shù)機(jī)器,但是新任leader還是不能準(zhǔn)確斷定這條日志是否是已提交。
Raft不能根據(jù)上一任期的日志是否被復(fù)制到大多數(shù)機(jī)器來決定是否提交日志。一旦當(dāng)前任期看到一條日志被提交,由于Log Matching Property保證,那么這條日志之前的日志已自動被提交。
在實(shí)際系統(tǒng)中,我們有時(shí)候可能需要變更配置,例如需要替換宕機(jī)的機(jī)器或者增加日志的副本數(shù)。為了保證安全,配置變更采用兩階段的方法。這里有很多方法可以實(shí)現(xiàn)兩階段,例如:有的系統(tǒng)在第一個(gè)階段來停止舊配置,這樣就不能響應(yīng)客戶端的請求;然后第二階段切換到新配置。Raft集群第一階段
會過渡到遷移配置(我們稱之為聯(lián)合一致性配置joint consensus);一旦聯(lián)合一致性被提交,系統(tǒng)將切換到新配置。joint consensus配置組合了老配置和新配置。
Raft的客戶端將自己的請求發(fā)送到leader。當(dāng)一個(gè)客戶端首次啟動,它會隨機(jī)的選擇集群的一臺機(jī)器。如果客戶端的首次選擇不是leader,這臺機(jī)器將拒絕客戶端的請求,并會告知自己最近監(jiān)聽到的 leader。如果leader宕機(jī),客戶端的請求將會超時(shí),客戶端可以隨機(jī)的選擇機(jī)器進(jìn)行重試。
Raft的目標(biāo)是實(shí)現(xiàn)線性語義(每個(gè)操作都是立刻被執(zhí)行的),然而,目前為止我們描述的 Raft可以重復(fù)多次的執(zhí)行一條命令;例如,如果leader提交了日志但是還沒有來得及響應(yīng)客戶端就宕機(jī),那么客戶端將會換一個(gè)leader重試之前的命令。解決方法就是客戶端給每個(gè)命令一個(gè)唯一的編號,那么,狀態(tài)機(jī)記錄每個(gè)客戶端處理的最新的編號。一旦接受到一條命令它的序列號已經(jīng)被執(zhí)行過,直接響應(yīng)這個(gè)請求但是不重新執(zhí)行這個(gè)請求。
以上是“Raft一致性算法有哪些”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。