時間戳伺服器id是什麼
A. IP和ID有什麼不同
1 本身代表含義不同:
ID是IDentity的縮寫,身份標識號碼的意思。
IP是Internet Protocol的縮寫,中文簡稱為「源雀網協」,也就是為計算機網路相互連接進行通信而設計的協議。
2 作用不同:
IP是網路內參數,起到連接的作用;
ID是賬戶身份,起到聯系、驗證的作用。
3 網路中扮演角色不同:
IP是你的唯一上網地址,也就是你上網的唯一憑證,相當於你的家庭住址;
ID是你在某個網站申請的用戶名,可以有多個,並且ID在你申請的網站外是沒有用的。
(1)時間戳伺服器id是什麼擴展閱讀:
IP地址:
所謂IP地址就是給每個連接在互聯網上的主機分配的一個32位地址。
IP地址就好像電話號碼(地址碼):有了某人的電話號碼,你就能與他通話了。同樣,有了某台主機的IP地址,你就能與這台主機通信了。
按照TCP/IP(Transport Control Protocol/Internet Protocol,傳輸控制協議/Internet協議)協議規定,IP地址用二進制來表示,每個IP地址長32bit,比特換算成位元組,就是4個位元組。
例如一個採用二進制形式的IP地址是一串很長的數字,人們處理起來也太費勁了。為了方便人們的使用,IP地址經常被寫緩裂豎成十進制的形式,中間使用符號「.」分開不同的位元組。
於是,上面的IP地址可以表示為「10.0.0.1」。IP地址的這種表示法叫做「點分十進製表示法」,這顯然比1和0容易記憶得多。
有人會以為,一台計算機只能有一個IP地址,這種觀點是錯誤的。我們可以指定一台計算機具有多個IP地址,因此在訪問互聯網時,不要以為一個IP地址就是一台計算機;
另外,通過特定的技術,也可以使多台伺服器共用一個IP地址,這些伺服器在用戶看起來就像一台主機似的。
將IP地址分成了網路號和主機號兩部分,擾大設計者就必須決定每部分包含多少位。網路號的位數直接決定了可以分配的網路數(計算方法2^網路號位數);
主機號的位數則決定了網路中最大的主機數(計算方法2^主機號位數-2)。然而,由於整個互聯網所包含的網路規模可能比較大,也可能比較小,設計者最後聰明的選擇了一種靈活的方案:
將IP地址空間劃分成不同的類別,每一類具有不同的網路號位數和主機號位數。
IP地址是IP網路中數據傳輸的依據,它標識了IP網路中的一個連接,一台主機可以有多個IP地址。IP分組中的IP地址在網路傳輸中是保持不變的。
IP (網路之間互連的協議)-網路
B. 如何產生唯一的server id
我們都知道Mysql用server-id來唯一的標識某個資料庫實例,並在鏈式或雙主復制結構中用它來避免sql語句的無限循環。這篇文章分享下我對server-id的理解,然後比較和權衡生成唯一server-id的幾種方式。
server_id的用途
簡單說來,server_id有兩個用途:
1. 用來標記binlog event的源產地,就是SQL語句最開始源自於哪裡。
2. 用於IO_thread對主庫binlog的過濾。如果沒有設置 replicate-same-server-id=1 ,那麼當從庫的io_thread發現event的源與自己的server-id相同時,就會跳過該event,不把該event寫入到relay log中。從庫的sql_thread自然就不會執行該event。這在鏈式或雙主結構中可以避免sql語句的無限循環。
注意:相同server-id的event在io_thread這一層就過濾了;而對於replicate-(do|ignore)-等規則,則是在sql_thread這一層過濾的。io_thread和sql_thread都有過濾的功能。
server_id為何不能重復
在同一個集群中,server-id一旦重復,可能引發一些詭異問題。
看看下面兩種情況:
圖1:主庫與從庫的server-id不同,但是兩個或多個從庫的server-id相同
這種情況下復制會左右搖擺。當兩個從庫的server-id相同時,如果從庫1已經連接上主庫,此時從庫2也需要連接到主庫,發現之前有server-id相同的連接,就會先注銷該連接,然後重新注冊。
參考下面的代碼片段:
repl_failsafe (register_slave) download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int register_slave(THD* thd, uchar* packet, uint packet_length)
{
int res;
SLAVE_INFO *si;
...
if (!(si->master_id= uint4korr(p)))
si->master_id= server_id;
si->thd= thd;
pthread_mutex_lock(&LOCK_slave_list);
/* 先注銷相同server-id的連接*/
unregister_slave(thd,0,0);
/* 重新注冊*/
res= my_hash_insert(&slave_list, (uchar*) si);
pthread_mutex_unlock(&LOCK_slave_list);
return res;
...
}
兩台從庫不停的注冊,不停的注銷,會產生很多relay log文件,查看從庫狀態會看到relay log文件名不停改變,從庫的復制狀態一會是yes一會是正在連接中。
圖2:鏈式或雙主結構中,主庫與從庫的server-id相同
從庫1同時又是relay資料庫,它能正確同步,然後把relay-log內容重寫到自己的binlog中。當server-id為100的從庫2 io線程獲取binlog時,發現所有內容都是源自於自己,就會丟棄這些event。因此從庫2無法正確同步主庫的數據。只有直接寫relay server的event能正確同步到從庫2。
上面兩種情況可以看到,在同一個replication set中,保持server-id的唯一性非常重要。
server_id的動態修改
無意中發現 server-id 竟然是可以動態修改的,可別高興的太早。好處是,上面圖1的情況下,直接修改其中一個從庫的server-id就可以解決server-id沖突的問題。壞處很隱蔽,如下圖的結構:
現在假設active-master因為某種原因與passive-master的同步斷開後,passive-master上進行了一些ddl變更。然後某dba突發奇想把passive-master的server-id修改為400。當雙master的復制啟動後,那些之前在passive-master上執行的server-id為200的ddl變更,會從此陷入死循環。如果是 alter table t engine=innodb ,它會一直不停,可能你會發現。但是像 update a=a+1; 這樣的sql,你很難發現。當然這種場景只是我的杜撰,這兒有個更真實的例子 主備備的兩個備機轉為雙master時出現的詭異slave lag問題 。
舉這兩個例子只是想說明修改server-id有點危險,最好不要去修改,那麼能一步到位生成它嗎?
如何生成唯一的server_id
常用的方法有如下幾種:
1. 採用隨機數
mysql的server-id是4位元組整數,范圍從0-4294967295,因此採用該范圍內的隨機數來作為server-id產生沖突的可能性是非常小的。
2. 採用時間戳
直接用date +%s來生成server-id。一天86400秒來計算,往後計算50年,最大的server-id也才使用到86400*365*50,完全在server-id范圍內。
3. 採用ip地址+埠
這是我們經常採用的方法。例如ip為192.168.122.23,埠為3309,那麼server-id可以寫為122233309。產生沖突的可能性比較小:遇到*.*.122.23 或者*.*.12.223,而且搭建了同一個replication set的3309才會出現。
4. 採用集中的發號器
在管理伺服器上採用自增的id來統一分配server-id。這可以保證不沖突,但是需要維護中心節點。
5. 分開管理每個replication set
在每個replication set中為mysql庫增加一個管理表,保證每個從庫的server-id不沖突。
哪一種更好
上面的幾種方法都不賴,但是:
1. 方法4加了維護負擔,而且開發環境、測試環境、線上環境都維護一套發號器的話,有點麻煩,混在一起又可能遇到網段隔離的風險,還有發號器資料庫許可權的問題難於控制。所以不推薦。
2. 方法5實現了自治,但是管理成本有點高。從庫要能夠寫主庫的server-id表,復雜。
3. 5種方法都存在的問題是,使用冷備的數據來擴容,server-id需要手動去修改,否則就與冷備源的server-id沖突。而且,當mysql啟動的時候,你無法判斷該mysql是剛通過備份擴容的,還是之前一直正常運行的。所以你不知道這個server-id到底要不要改。而我希望server-id對dba完全透明,又絕不產生沖突,即可徹底屏蔽這個討厭的東西。
建議的方法
其實很簡單。ipv4是4位元組的整數,與server-id的范圍完全一樣。我們認為只有ip地址+埠才能唯一的確定一個mysql實例,所以總是希望把ip信息和埠信息都集成到server-id中。但是別忘了,一個ip上不能同時啟動兩個一樣的埠。所以,server-id只需採用ip地址的整數形式!自定義的mysql啟動腳本強制對server-id進行檢查,發現server-id不對就進行糾正,然後啟動。上面所有的問題,都會迎刃而解。
C. bbo和zookeeper
bbo 是一個遠程調用服務的分布式框架,可以實現遠程通訊、動態配置、地址路由等等功能。比如在入門demo里的暴露服務,使得遠程調用的協議可以使用dobbo協議( bbo://x.x.x.x )或者其它協議,可以配置zookeeper集群地址,實現軟負載均衡並配置均衡方式等。在不搭配注冊中心的時候,它也是可以實現服務端和調用端的通信的,這種方式是點對點通信的,所謂「沒有中間商」。但是如果配置服務發布和調用端過多特別是集群的方式提供服務的時候,就會暴露許多的問題:增加節點需要修改配置文件、服務端機器宕機後不能被感知等。它可以通過集成注冊中心,來動態地治理服務發布和服務調用。相當於把服務注冊和發布推送的功能分攤給了(zookeeper)注冊中心。
Dubbo實現服務調用是通過RPC的方式,即客戶端和服務端共用一個介面(將介面打成一個jar包,在客戶端和服務端引入這個jar包),客戶端面向介面寫調用,服務端面向介面寫實現,中間的網路通信交給框架去實現。
咱們來看下Spring 配置聲明暴露服務,provider.xml文件
再來看服務消費者,consumer.xml文件
這就是典型的點對點的服務調用。當然我們為了高可用,可以在consumer.xml中配置多個服務提供者,並配置響應的負載均衡策略。
配置多個服務調用者在comsumer.xml的bbo:reference標簽的url屬性中加入多個地址,中間用分號隔開即可;配置負載均衡策略在comsumer.xml的bbo:reference標簽中增加loadbalance屬性即可,值可以為如下四種類型:
那麼目前的架構有什麼問題呢?
1.當服務提供者增加節點時,需要修改配置文件。
2.當其中一個服務提供者宕機時,服務消費者不能及時感知到,還會往宕機的服務發送請求。
這個時候就需要引入注冊中心了,Dubbo目前支持4種注冊中心(multicast、zookeeper、redis、simple)推薦使用Zookeeper注冊中心,要使用注冊中心,只需要將provider.xml和consumer.xml更改為如下:
如果zookeeper是一個集群,則多個地址之間用逗號分隔即可
把consumer.xml中配置的直連的方式去掉
注冊信息在zookeeper中如何保存?
啟動上面服務後,我們觀察zookeeper的根節點多了一個bbo節點及其他,圖示如下
最後一個節點中服務的地址,為什麼把最後一個節點標成綠色?因為最後一個節點是臨時節點,而其他節點是持久節點,這樣,當服務宕機時,這個節點就會自動消失,不再提供服務,服務消費者也不會再請求。如果部署多個DemoService,則providers下面會有好幾個節點,一個節點保存一個DemoService的服務地址。
其實一個zookeeper集群能被多個應用公用,因為不同的框架會在zookeeper上建不同的節點,互不影響。如bbo會創建一個/bbo節點,storm會創建一個/storm節點。
zookeeper 介紹:
zookeeper是 Apacahe Hadoop 的子項目,是一個樹型的目錄服務,支持變更推送,適合作為 Dubbo 服務的注冊中心,工業強度較高,可用於生產環境,並推薦使用。
流程說明:
支持以下功能:
補充:
bbo的協議使用什麼序列化框架?
bbo有多種協議,不同的協議默認使用不同的序列化框架。比如bbo協議默認使用 Hessian2 序列化(說明:Hessian2 是阿里在 Hessian 基礎上進行的二次開發,起名為Hessian2)。rmi協議默認為 java 原生序列化,http協議默認為為 json。
bbo的通信方式?
採用單一長連接和NIO非同步通信,基於Hessian2作為序列化協議。適合於小數據量(每次請求在100kb以內)大並發的服務調用,以及服務消費者機器數遠大於服務提供者機器數的情況。具體實現是消費者使用 NettyClient,提供者使用 NettyServer,Provider 啟動的時候,會開啟埠監聽,使用我們平時啟動 Netty 一樣的方式。而 Client 在 Spring getBean 的時候,會創建 Client,調用遠程方法的時候,將數據通過DubboCodec編碼發送到 NettyServer,然後 NettServer 收到數據後解碼,並調用本地方法,並返回數據,完成一次完美的 RPC 調用。
zookeeper選舉機制?
zookeeper選舉演算法默認的是FastLeaderElection,選舉機制的概念:
1.伺服器ID:比如有三台伺服器,編號分別是1、2、3,編號越大在選擇演算法中的權重越大。
2.事務ID:伺服器中存放的最大數據ID(致使ZooKeeper節點狀態改變的每一個操作都將更新事務id,即時間戳),值越大說明數據越新,在選舉演算法中數據越新權重越大。
3.邏輯時鍾,或者叫投票的次數,同一輪投票過程中的邏輯時鍾值是相同的。每投完一次票這個數據就會增加,然後與接收到的其它伺服器返回的投票信息中的數值相比,根據不同的值做出不同的判斷。
選舉狀態:LOOKING:競選狀態;FOLLOWING:隨從狀態,同步leader狀態,參與投票;OBSERVING:觀察狀態,同步leader狀態,不參與投票;LEADING:領導者狀態。
初次選舉簡述:
目前有5台伺服器,每台伺服器均沒有數據,它們的編號分別是1,2,3,4,5,按編號依次啟動,它們的選擇舉過程如下:
1.伺服器1啟動,給自己投票,然後發投票信息,由於其它機器還沒有啟動所以它收不到反饋信息,伺服器1的狀態一直屬於Looking。
2.伺服器2啟動,給自己投票,同時與之前啟動的伺服器1交換結果,由於伺服器2的編號大所以伺服器2勝出,但此時投票數沒有大於半數,所以兩個伺服器的狀態依然是LOOKING。
3.伺服器3啟動,給自己投票,同時與之前啟動的伺服器1,2交換信息,由於伺服器3的編號最大所以伺服器3勝出,此時投票數為3正好大於半數,所以伺服器3成為領導者,伺服器1,2成為小弟。
4.伺服器4啟動,給自己投票,同時與之前啟動的伺服器1,2,3交換信息,盡管伺服器4的編號大,但之前伺服器3已經勝出,所以伺服器4隻能成為小弟。
5.伺服器5啟動,後面的邏輯同伺服器4成為小弟。
如果中間有節點掛掉,只要有半數以上節點存活,就可以正常服務,如果leader掛掉,則所有節點處於Looking狀態 ,各自依次發起投票,投票包含自己的伺服器ID和最新事務ID,如果發現別人的事務id比自己大,也就是數據比自己新,那麼就重新發起投票,投票給目前已知最大的事務id所屬節點(事務id一樣,則數據id大的勝出)。每次投票後,伺服器都會統計投票數量,判斷是否有某個節點得到半數以上的投票。如果存在這樣的節點,該節點將會成為准Leader,狀態變為Leading。其他節點的狀態變為Following。
引用:
https://www.cnblogs.com/iisme/p/10620125.html