中間件

redis是什么

redis是一個(gè)非關(guān)系型數(shù)據(jù)庫(kù),以KV結(jié)構(gòu)存儲(chǔ)數(shù)據(jù),提供了多種數(shù)據(jù)類型和各自的本地方法,單線程處理數(shù)據(jù)本地方法,基于內(nèi)存存儲(chǔ),吞吐量大,集群部署高可用,基于redis這些特性我們很簡(jiǎn)單的可以實(shí)現(xiàn)一些功能,比如訂閱發(fā)布、排行榜、計(jì)數(shù)器等。

redis和memcache區(qū)別

redis單線程,多種數(shù)據(jù)類型,豐富的本地方法,有持久化;支持cluster分布式;
memecache多線程,只有String,只有g(shù)etset,無(wú)持久化;客戶端分布式;memcache使用固定大小的內(nèi)存塊存儲(chǔ)數(shù)據(jù),內(nèi)存利用率低

redis的性能(有品1)

redis單機(jī)性能能達(dá)到10w吞吐,單機(jī)開啟6.0提供的IO線程峰值可以達(dá)到15w

redis為什么是單線程的還可以這么快(有品1)

IO多路復(fù)用監(jiān)聽(tīng)多個(gè)socket事件,等數(shù)據(jù)讀取完畢進(jìn)入核心線程執(zhí)行;基于內(nèi)存,沒(méi)有磁盤尋址耗時(shí);核心線程只做計(jì)算,充分利用CPU;單線程沒(méi)有線程切換消耗;單線程天生線程安全,不需要加鎖;加上本地?cái)?shù)據(jù)結(jié)構(gòu)的優(yōu)化

redis數(shù)據(jù)類型和使用場(chǎng)景

string 字符串、整數(shù)、浮點(diǎn)數(shù);二進(jìn)制安全;最大值512m;緩存、計(jì)數(shù)器
list 列表;隊(duì)列、
set 無(wú)序不重復(fù)列表;點(diǎn)贊列表
sortset 有序不重復(fù)列表;排行榜
hash 包含鍵值對(duì)的散列表;最大長(zhǎng)度為2^32 -1 ;適合存儲(chǔ)對(duì)象,對(duì)某一屬性單獨(dú)操作
bit 位圖;布隆過(guò)濾器
hyperloglogs 基數(shù)統(tǒng)計(jì);

redis底層數(shù)據(jù)結(jié)構(gòu)

sds 字符串存儲(chǔ);擴(kuò)容最大1m,小于1m時(shí)double;c語(yǔ)法string以空座位結(jié)束;len、free、buf[];惰性釋放,使用free記錄
dict 字典;包含兩個(gè)hash表,方便rehash,擴(kuò)容時(shí),將其中一個(gè)hash表rehash到另一個(gè)表中,交換兩表身份;漸進(jìn)式rehash
ziplist 壓縮列表;節(jié)省內(nèi)存;
quicklist 每個(gè)quicklist節(jié)點(diǎn)就是一個(gè)ziplist,具備壓縮列表的特性;list的實(shí)現(xiàn),雙端操作o(1)
skiplist 跳躍表,每個(gè)節(jié)點(diǎn)有指向更遠(yuǎn)節(jié)點(diǎn)的指針,從空間上看好像跳躍一下,
intset 整數(shù)set

ziplist

包含的元素較少、并且每個(gè)元素要么是小整數(shù)要么是長(zhǎng)度較小的字符串時(shí),redis將會(huì)用ziplist作為hash、zset鍵的底層實(shí)現(xiàn)
ziplist是由一系列特殊編碼的連續(xù)內(nèi)存塊組成的順序存儲(chǔ)結(jié)構(gòu),雙向鏈表,類似于數(shù)組,ziplist在內(nèi)存中是連續(xù)存儲(chǔ)的,為了節(jié)省內(nèi)存 每個(gè)元素所占的內(nèi)存大小可以不同,每個(gè)節(jié)點(diǎn)可以用來(lái)存儲(chǔ)一個(gè)整數(shù)或者一個(gè)字符串
prevlength(可變長(zhǎng))、encoding(數(shù)字8位,字符串8、20、40)、data;
特殊編碼,int不再是固定32位,大數(shù)就用更長(zhǎng)的位數(shù)存,小數(shù)就用短的位數(shù)存
插入數(shù)據(jù),需要計(jì)算插入地址,ziplist擴(kuò)容后長(zhǎng)度,插入位置之后的數(shù)據(jù)要整體向后移,可能會(huì)產(chǎn)生數(shù)據(jù)拷貝
超過(guò)512個(gè)節(jié)點(diǎn) 有大于64字節(jié)的節(jié)點(diǎn),hash回有ziplist切換為hashtable

redis哨兵模式(有品1)

redis哨兵不處理消息,監(jiān)控master的健康狀態(tài),主觀下線、客觀下線,選舉新master;本身也可以集群部署,高可用

redis cluster(有品1)

redis服務(wù)端提供的分布式功能;hash槽,16384槽位;每個(gè)服務(wù)負(fù)責(zé)一部分槽位,互為主從;客戶端連接一個(gè)服務(wù)就可以;可以使用哨兵;增刪節(jié)點(diǎn)需要運(yùn)維參與,移動(dòng)槽位;

redis的RDB

save和bgsave命令,創(chuàng)建實(shí)時(shí)內(nèi)存快照,save是同步阻塞創(chuàng)建,bgsave是fork一個(gè)子進(jìn)程進(jìn)行快照,快照過(guò)程中主進(jìn)程使用copyOnWrite方式繼續(xù)工作;
IO占用CUP;無(wú)法記錄實(shí)時(shí)數(shù)據(jù);服務(wù)宕機(jī),數(shù)據(jù)存在丟失部分風(fēng)險(xiǎn);save(m,n) ,每m條或ns執(zhí)行一次RDB

redis的AOF

向日志文件里拼接執(zhí)行命令,每執(zhí)行同步,自動(dòng)同步;數(shù)據(jù)全;rewrite壓縮文件;文件太大

redis主從同步

增量復(fù)制
主庫(kù)維護(hù)緩存列表,主從維護(hù)offset,當(dāng)從庫(kù)的offset在主庫(kù)范圍內(nèi),執(zhí)行增量復(fù)制,直接讀取緩存列表中的執(zhí)行記錄

全量復(fù)制
剛上線、失聯(lián)之后offset不再主庫(kù)buff范圍的從庫(kù)需要執(zhí)行全量復(fù)制
redis生成一個(gè)RDB文件發(fā)送給從服務(wù),從服務(wù)使用RDB恢復(fù)數(shù)據(jù);IO問(wèn)題

redis分布式鎖實(shí)現(xiàn)(有品1)

利用setNx+setEx或者set(k,v,nx,px)方法的原子性,想某key寫入一個(gè)線程ID,刪除時(shí)先判斷線程ID,lua腳本原子操作,防止錯(cuò)誤刪除;本地使用cnt記錄重入次數(shù);key設(shè)置過(guò)期時(shí)間防止死鎖;redisson看門狗解決續(xù)期;集群?jiǎn)栴},redLock解決

redisson看門狗定時(shí)器,10s續(xù)期一次
redlock 按順序向集群每個(gè)節(jié)點(diǎn)請(qǐng)求一個(gè)鎖,根據(jù)一定超時(shí)時(shí)間判斷是否跳過(guò),超過(guò)一半的節(jié)點(diǎn)加鎖成功就返回

redis6.0做了什么(有品1)

增加IO線程,IO線程處理多路復(fù)用之后接收到文件準(zhǔn)備好的消息(網(wǎng)卡->內(nèi)核socket緩沖),讀取數(shù)據(jù)的操作(內(nèi)核socket緩存->用戶內(nèi)存)

redis事務(wù)

一個(gè)事務(wù)包含了多個(gè)命令,原子操作
事務(wù)中的多個(gè)命令被一次性發(fā)送給服務(wù)器,這種方式被稱為流水線,減少網(wǎng)絡(luò)通信次數(shù),提升性能
只校驗(yàn)語(yǔ)法,如果失敗是不會(huì)回滾的,
MULTI 和 EXEC 命令將事務(wù)操作包圍起來(lái)

redisKey淘汰策略

先進(jìn)先出
LRU 最長(zhǎng)時(shí)間未使用
LFU 單位時(shí)間內(nèi)最少使用
隨機(jī)

redisKey的過(guò)期

定時(shí)過(guò)期(時(shí)間事件,設(shè)置了過(guò)期時(shí)間的key的列表中拿一部分,過(guò)期一部分)+取時(shí)過(guò)期(拿到數(shù)據(jù),發(fā)現(xiàn)過(guò)期了,執(zhí)行過(guò)期操作)

什么是zookeeper

分布式協(xié)同框架,為分布式項(xiàng)目提供一致性服務(wù)。內(nèi)存讀寫,強(qiáng)一致性,事件通知,高可用,leader和follower;

zab協(xié)議

1.消息同步 先發(fā)消息,等待大多數(shù)follower反饋之后,再發(fā)一條commit
2.選舉 集群?jiǎn)?dòng)時(shí)、leader宕機(jī)時(shí)

zk的數(shù)據(jù)結(jié)構(gòu)

zk是一個(gè)樹狀的存儲(chǔ)結(jié)構(gòu),以文件路徑的方式訪問(wèn)對(duì)應(yīng)節(jié)點(diǎn),
每一個(gè)節(jié)點(diǎn)既是一個(gè)文件也是一個(gè)文件夾,節(jié)點(diǎn)路徑是唯一的,可以用做命名服務(wù)
節(jié)點(diǎn)的數(shù)據(jù)結(jié)構(gòu)是Znode,
維護(hù)數(shù)據(jù)、權(quán)限(ACL)、名稱、stat(dataVersion每次修改節(jié)點(diǎn)數(shù)都會(huì)++,cversion子節(jié)點(diǎn)發(fā)生變化++,aclVersion發(fā)生變化++)、cZxid創(chuàng)建事物ID、mZxid修改事物ID、時(shí)間戳

zk的節(jié)點(diǎn)類型

永久節(jié)點(diǎn) 需要主動(dòng)刪除
臨時(shí)節(jié)點(diǎn) 創(chuàng)建的節(jié)點(diǎn)的session失效就會(huì)刪除

無(wú)序節(jié)點(diǎn)
有序節(jié)點(diǎn) 在同一個(gè)父節(jié)點(diǎn)下有序,在name后面拼上順序ID

zk的事件通知機(jī)制

zk提供節(jié)點(diǎn)的增刪改和子節(jié)點(diǎn)的增刪改事件通知;
客戶端和服務(wù)端都維護(hù)一個(gè)事件監(jiān)聽(tīng)列表,客戶端添加監(jiān)聽(tīng)之后進(jìn)入本地列表,并同步到服務(wù)端,服務(wù)端事件觸發(fā)后通知到客戶端,客戶端根據(jù)消息內(nèi)的path去拉取數(shù)據(jù),
這個(gè)監(jiān)聽(tīng)是一次性的,如果持續(xù)監(jiān)聽(tīng),需要在此添加

zk實(shí)例的三種狀態(tài)

Looking 剛加入集群
Leading leader狀態(tài)
Flowing flowing狀態(tài)

zk實(shí)例的三種身份

Observer 只同步數(shù)據(jù),不參與選舉,擴(kuò)展集群讀操作的性能而不影響寫
leader 負(fù)責(zé)數(shù)據(jù)讀寫,同步
flower 負(fù)責(zé)讀請(qǐng)求,寫請(qǐng)求轉(zhuǎn)發(fā)給leader

zk的Zxid

Zxid是zk提供的事務(wù)ID,是一個(gè)64位的數(shù)字,高32位代表leader周期,低32位為自增序列;事務(wù)ID每次同步都會(huì)發(fā)送給follower

zk的MyId

zk每臺(tái)實(shí)例應(yīng)當(dāng)配置一個(gè)唯一的ID

zk選舉過(guò)程

網(wǎng)狀投票,投票原則,投給zxid更大的,如果zxid一樣投給myid更大的;當(dāng)一臺(tái)服務(wù)獲取到半數(shù)以上的節(jié)點(diǎn)投票,自動(dòng)成為leader
啟動(dòng)階段:假設(shè)3臺(tái)實(shí)例的集群
1.實(shí)例1加入集群,發(fā)現(xiàn)只有自己,投票給自己,沒(méi)有達(dá)到半數(shù)
2.實(shí)例2加入集群,投票給自己,實(shí)例1接到2的選票,發(fā)現(xiàn)2的myid大一些,更改選票發(fā)給2,2接收選票發(fā)現(xiàn)達(dá)到半數(shù)以上,成為leader
3.實(shí)例3加入集群,發(fā)現(xiàn)已經(jīng)有l(wèi)eader,自動(dòng)成為follower

崩潰恢復(fù)階段:假設(shè)3臺(tái)
1.所有人投票給自己并發(fā)送給其他所有實(shí)例
2.接到別人選表之后對(duì)比zxid和myid,根據(jù)規(guī)則更改選票發(fā)出去
3.有一臺(tái)達(dá)到半數(shù)成為leader

zk腦裂問(wèn)題

腦裂問(wèn)題發(fā)生在leader宕機(jī)重新選舉之后,宕機(jī)的舊leader又加入集群,這樣集群就存在了兩個(gè)leader;
新leader會(huì)頭部消息給舊leader,舊l拿到zxid發(fā)現(xiàn)高32位的l周期已經(jīng)增加,自己就成就followe

zk的session機(jī)制

客戶端啟動(dòng)之后會(huì)與zk維護(hù)一條長(zhǎng)鏈接,zk會(huì)為這個(gè)客戶端創(chuàng)建一個(gè)session并分配一個(gè)sessionId,session有過(guò)期時(shí)間,每次主動(dòng)通訊,或者心跳都會(huì)給session續(xù)期;
心跳中斷后,zk會(huì)嘗試重新發(fā)起連接,如果成功,保持session,如果失敗,session失效

zk的分布式鎖實(shí)現(xiàn)

先創(chuàng)建一個(gè)永久鎖節(jié)點(diǎn),嘗試在這個(gè)鎖節(jié)點(diǎn)下創(chuàng)建有序臨時(shí)節(jié)點(diǎn),排在第一位的節(jié)點(diǎn)獲得鎖,
后面的節(jié)點(diǎn)分別監(jiān)聽(tīng)它之前的一個(gè)節(jié)點(diǎn),
鎖釋放之后,刪除臨時(shí)節(jié)點(diǎn),第二順位的會(huì)接到通知,獲取鎖
臨時(shí)節(jié)點(diǎn)特性防死鎖
可重入可以在線程內(nèi)部或者臨時(shí)節(jié)點(diǎn)維護(hù)重入次數(shù)
zk分布式鎖可以規(guī)避驚群效應(yīng)

kafka是什么

高性能的分布式消息隊(duì)列,百萬(wàn)吞吐;不支持延遲隊(duì)列;多用于日志收集等海量數(shù)據(jù)場(chǎng)景;磁盤讀寫,持久化;由Scala和Java編寫

kafka的性能(有品1)

百萬(wàn)吞吐;磁盤順序讀寫接近內(nèi)存;pagecache;零拷貝;批量讀;IO壓縮傳輸;分區(qū)分段+索引

pagecache頁(yè)存 Pagecache是通過(guò)將磁盤中的數(shù)據(jù)緩存到內(nèi)存中,從而減少磁盤I/O操作;pagecache中的數(shù)據(jù)更改時(shí)能夠被同步到磁盤上,page回寫;pagecache刷盤sync fsync 內(nèi)存少,達(dá)到時(shí)間
零拷貝 文件->內(nèi)核->用戶內(nèi)存->內(nèi)核soket緩沖區(qū)->網(wǎng)卡 四次copy,硬件->內(nèi)核是有CMD完成;CMD提供了文件->網(wǎng)卡操作

kafka架構(gòu)

邏輯架構(gòu)
broker 服務(wù)器
topic 主題,可以認(rèn)為是一個(gè)隊(duì)列
partition 分區(qū),每一個(gè)topic可以分為多個(gè)partition,分區(qū)是為了提升性能;每個(gè)broker會(huì)有多個(gè)partition,互為主備;
producter 生產(chǎn)者 生產(chǎn)消息
consumer 消費(fèi)者 消費(fèi)消息;一個(gè)partition同時(shí)只能被同一個(gè)消費(fèi)者組里的一個(gè)消費(fèi)者消費(fèi)
consumegroup 消費(fèi)者組,同一個(gè)消費(fèi)者組只能消費(fèi)1次;實(shí)現(xiàn)多次消費(fèi),用消費(fèi)者組

物理架構(gòu)
segment文件 每一個(gè)partition使用多個(gè)segment文件存儲(chǔ),通過(guò)索引文件定位消息在哪個(gè)segement中;分段存儲(chǔ)是為了防止文件過(guò)大,
.log文件 .index文件

kafka主從

kafka主從是為了容災(zāi)和提升服務(wù)高可用,每個(gè)broker里的有多個(gè)partition,多個(gè)partition可以互為主備,與主完全同步的備進(jìn)入ISR列表

kafka的rebalance

rebalance指,partition和consumer的重新匹配,這個(gè)過(guò)程kafka是不處理任何消息的;
主要發(fā)生在,topic數(shù)量發(fā)生變化,partition數(shù)量發(fā)生變化,consumer數(shù)量發(fā)生變化,當(dāng)前連接的consumer消費(fèi)超時(shí)或者掛了
通過(guò)Coordinator(每個(gè)broker都會(huì)啟動(dòng)一個(gè)Coordinator服務(wù),存儲(chǔ)group的offset等信息,0.9之前是zk)協(xié)調(diào),選出group中一個(gè)consumer作為leader,進(jìn)行partition分配

kafka的瓶頸

當(dāng)topic數(shù)量過(guò)多的時(shí)候,由于kafka的partition的segment存儲(chǔ)方式,會(huì)產(chǎn)生更多的文件,順序讀寫退化為隨機(jī)讀寫

kafka如何保證順序

每個(gè)partition順序?qū)?,每個(gè)partition同時(shí)只能被被同一個(gè)消費(fèi)者組里的一個(gè)消費(fèi)者消費(fèi),保證消費(fèi)順序

kafka如何保證消息可靠(qzwl1)

生產(chǎn)消息時(shí)可以選擇ack模式,默認(rèn)異步,ack.all 同步所有ISR列表內(nèi)的備份;
kafka落盤,先寫入pagecache 服務(wù)器宕機(jī)可能丟失,實(shí)時(shí)刷盤
消費(fèi)時(shí),可選自動(dòng)提交和主動(dòng)提交,在提交offset之后,才認(rèn)為消息被消費(fèi);自動(dòng)提交有丟消息的風(fēng)險(xiǎn),主動(dòng)提交有重復(fù)消費(fèi)風(fēng)險(xiǎn)

kafka事務(wù)

kafka從0.11開始支持事務(wù);原子寫入多條消息;

kafka的分區(qū)同步機(jī)制

每個(gè)patition有幾個(gè)關(guān)鍵的offset ,只同步ISR(Inof-Sync Replicas)列表分區(qū),leader負(fù)責(zé)維護(hù)和跟蹤ISR
LogEndOffset 下一個(gè)分配的偏移量
HighWartermark 消費(fèi)者最高水位線 新消息提交leader后同步所有follower,之后更新HW,此消息才可以被消費(fèi)
FirstMessageOffset

rabbitmq

erlang開發(fā)消息隊(duì)列,開源,跨語(yǔ)言跨平臺(tái),可靠消息傳輸

rabbitmq架構(gòu)

Broker:實(shí)例,它提供一種傳輸服務(wù),它的角色就是維護(hù)一條從生產(chǎn)者到消費(fèi)者的路線,保證數(shù)據(jù)能按照指定的方式進(jìn)行傳輸,
Exchange:消息交換機(jī),它指定消息按什么規(guī)則,路由到哪個(gè)隊(duì)列。
Queue:消息的載體,每個(gè)消息都會(huì)被投到一個(gè)或多個(gè)隊(duì)列。
Binding:綁定,它的作用就是把exchange和queue按照路由規(guī)則綁定起來(lái).
Routing Key:路由關(guān)鍵字,exchange根據(jù)這個(gè)關(guān)鍵字進(jìn)行判斷消息投遞哪些queue
vhost:虛擬主機(jī),一個(gè)broker里可以有多個(gè)vhost,用作不同用戶的權(quán)限分離。
Producer:消息生產(chǎn)者,就是投遞消息的程序,面向交換機(jī)
Consumer:消息消費(fèi)者,就是接受消息的程序.,面向隊(duì)列

Channel:消息通道,在客戶端的每個(gè)連接里,可建立多個(gè)channel,通過(guò)一個(gè)鏈接可以并發(fā)發(fā)送消息和接收消息

rabbitmq交換機(jī)類型

扇形交換機(jī) 路由到所有綁定的queue上
DIRECT交換機(jī) 投遞到所有routekey相等的queue上
Topic交換機(jī) 投遞到所有routekey匹配的queue上,這里指的匹配是利用通配符,topic的routekey是一種以.分隔的字符串,每分隔的一段都可以用作匹配,比如..red.*會(huì)比配所有第三段為red的消息
HEADERS交換機(jī) 消息頭訂閱,消息發(fā)布前,為消息定義一個(gè)或多個(gè)鍵值對(duì)的消息頭,然后消費(fèi)者接收消息同時(shí)需要定義類似的鍵值對(duì)請(qǐng)求頭:(如:x-mactch=all或者x_match=any),只有請(qǐng)求頭與消息頭匹配,才能接收消息,忽略RoutingKey.

rabbitmq怎么生產(chǎn)消息

生產(chǎn)者面向交換機(jī)
channel.basicPublish(excange_name,route_key,false,bs,"test".getBytes());

rabbitmq怎么消費(fèi)消息

消費(fèi)者面向的是queue,消費(fèi)相同routekey、queue的會(huì)做均衡,消費(fèi)相同routekey和不同queue的消費(fèi)做會(huì)做復(fù)制
channel.basicConsume(QUEUE_AUTODELETE, AutoAck, consumer)
消息確認(rèn),ack,

rabbitmq事務(wù)

事務(wù)的實(shí)現(xiàn)主要是對(duì)信道(Channel)的設(shè)置,
只有在autoAck=false時(shí)生效

rabbitmq的AMQP

高級(jí)消息隊(duì)列協(xié)議
在 AMQP 模型中,消息的 producer 將 Message 發(fā)送給 Exchange,Exchange 負(fù)責(zé)交換 / 路由,將消息正確地轉(zhuǎn)發(fā)給相應(yīng)的 Queue。消息的 Consumer 從 Queue 中讀取消息。

rabbitmq集群高可用

單一模式 一臺(tái)實(shí)例
普通模式 每臺(tái)實(shí)例有相同的元數(shù)據(jù)、隊(duì)列結(jié)構(gòu),數(shù)據(jù)只存在一個(gè)實(shí)例上,消費(fèi)時(shí),去數(shù)據(jù)存儲(chǔ)的實(shí)例取出
鏡像模式 每臺(tái)實(shí)例可以維護(hù)其他隊(duì)列的鏡像,消費(fèi)時(shí),直接從鏡像發(fā)送,需要做節(jié)點(diǎn)的同步

rabbit死信隊(duì)列

長(zhǎng)時(shí)間沒(méi)有被消費(fèi)或者消費(fèi)失敗的消息,會(huì)進(jìn)入死信隊(duì)列,死信隊(duì)列也是一個(gè)隊(duì)列,死信隊(duì)列中的消息也可以被消費(fèi)
直接訂閱某個(gè)隊(duì)列的死信隊(duì)列,設(shè)置隊(duì)列超時(shí)時(shí)間,來(lái)實(shí)現(xiàn)延時(shí)隊(duì)列;
先聲明一個(gè)交換機(jī)和一個(gè)隊(duì)列,將這個(gè)隊(duì)列關(guān)聯(lián)一個(gè)私信交換機(jī),聲明這個(gè)私信交換機(jī),聲明死信隊(duì)列,將死信隊(duì)列綁定私信交換機(jī);
消息超時(shí)或消費(fèi)失敗,會(huì)由隊(duì)列進(jìn)入私信交換機(jī),由私信交換機(jī)進(jìn)入死信隊(duì)列

rabbitmq的消息持久化

持久化隊(duì)列需要聲明durable=True

rabbitmq消息可靠性

  • 開啟事物
  • 開啟confirm 基于回調(diào)的消息確認(rèn)
  • 開啟持久化 開啟鏡像模式
  • 關(guān)閉自動(dòng)ack

消息重試機(jī)制,默認(rèn)三次

rabbitmq的鏡像模式

rabbitmq部署有三種方式,單機(jī)部署、普通集群部署、鏡像集群部署
每個(gè)隊(duì)列都有對(duì)應(yīng)的鏡像隊(duì)列作為備份,每個(gè)broker會(huì)啟動(dòng)一個(gè)GM服務(wù),GM服務(wù)起到協(xié)調(diào)作用,所有GM組成GMgroup環(huán)形鏈表,由master通知next,直到leader收到通知同步結(jié)束
master宕機(jī)之后存在時(shí)間最長(zhǎng)的slave升級(jí)成master

activemq rabbtimq rocketmq kafka的區(qū)別

activemq jms規(guī)范;支持事物、xa協(xié)議;社區(qū)較少
rabbitmq erlang開發(fā),對(duì)java二次開發(fā)不友好;跨語(yǔ)言、跨平臺(tái);社區(qū)文檔有優(yōu)勢(shì);需要學(xué)習(xí)amqp協(xié)議
rocketmq java開發(fā);參考kafka設(shè)計(jì),優(yōu)化kafka瓶頸,吞吐量高
kafka java開發(fā);吞吐量高,高可用,技術(shù)成熟,單機(jī)超過(guò)64分區(qū)有性能問(wèn)題,沒(méi)有延遲隊(duì)列
zeromq 無(wú)持久化,數(shù)據(jù)協(xié)議要自己定義,更像是一個(gè)通訊框架;快

rocketmq架構(gòu)

邏輯架構(gòu)
nameserver 負(fù)責(zé)broker注冊(cè)與發(fā)現(xiàn),存儲(chǔ)broker元數(shù)據(jù),心跳,路由;集群部署
broker 服務(wù)器
topic 主題,可以認(rèn)為是一個(gè)隊(duì)列
queue 隊(duì)列,topic的分片,每一個(gè)topic可以分為多個(gè)partition,分區(qū)是為了提升性能;每個(gè)broker會(huì)有多個(gè)partition,互為主備;
producter 生產(chǎn)者 生產(chǎn)消息
consumer 消費(fèi)者 消費(fèi)消息;一個(gè)partition同時(shí)只能被同一個(gè)消費(fèi)者組里的一個(gè)消費(fèi)者消費(fèi)
consumegroup 消費(fèi)者組,同一個(gè)消費(fèi)者組只能消費(fèi)1次;實(shí)現(xiàn)多次消費(fèi),用消費(fèi)者組

物理架構(gòu)
commitLog message持久化的文件

rocketmq延時(shí)消息原理

只支持固定的幾種延時(shí)時(shí)間
原理就是,延時(shí)消息先進(jìn)入固定時(shí)間的延時(shí)隊(duì)列,到時(shí)間后,放到真實(shí)隊(duì)列下

rocketmq優(yōu)化了哪些功能

1.通過(guò)commitLog解決了kafka順序讀寫退化問(wèn)題
2.優(yōu)化重試機(jī)制,消費(fèi)失敗鏈接超時(shí)自動(dòng)切換broker

網(wǎng)關(guān)是做什么的

網(wǎng)關(guān)是一個(gè)Api服務(wù)器,是系統(tǒng)的唯一入口。網(wǎng)關(guān)的最重要的職責(zé)就是路由轉(zhuǎn)發(fā)。鑒權(quán),日志,靜態(tài)資源響應(yīng)等。
與Nginx的區(qū)別是,nginx只能做路由轉(zhuǎn)發(fā),處理靜態(tài)資源,無(wú)法擴(kuò)展一些公共業(yè)務(wù)功能。
可以用nginx對(duì)網(wǎng)關(guān)服務(wù)做代理,網(wǎng)關(guān)服務(wù)對(duì)業(yè)務(wù)服務(wù)做代理。
gateway 和 netflix zuul

gateway原理

gateway使用netty作為通訊框架,
三大組件:
路由 一個(gè)ID、一個(gè)uri、一組斷言、一組過(guò)濾器組成
斷言 用來(lái)匹配http中的請(qǐng)求符合那個(gè)uri
過(guò)濾器 對(duì)請(qǐng)求和響應(yīng)做處理

什么是eureka

eureka是一個(gè)注冊(cè)中心,是spring cloud中的一個(gè)組件,用于服務(wù)的注冊(cè)與發(fā)現(xiàn)。
eureka server 注冊(cè)中心
service provider 服務(wù)提供方,將服務(wù)注冊(cè)到注冊(cè)中心
service consumer 服務(wù)消費(fèi)方,從注冊(cè)中心獲取服務(wù)列表

zk是CP,eureka是AP保證eurekaserver的高可用性,允許一定的數(shù)據(jù)不一致

什么是nacos

nacos是alibaba開源的 配置中心和注冊(cè)中心
兩種模式支持ap或者cp;

eurake nacos zk的區(qū)別

eurake ap;http
nacos ap/cp;http
zk cp;tcp

Hystrix原理

限流
1.線程池
2.令牌桶
熔斷,基于catch異常

sentinel原理

sentinel通過(guò)控制資源并發(fā)線程數(shù)來(lái)進(jìn)行限流;
資源是sentinel中的抽象概念,一個(gè)方法,一個(gè)uri都可以被定義為一個(gè)資源;
通過(guò)對(duì)資源配置規(guī)則,進(jìn)行限制
通過(guò)響應(yīng)時(shí)間對(duì)資源進(jìn)行降級(jí),當(dāng)依賴的資源出現(xiàn)響應(yīng)時(shí)間過(guò)長(zhǎng)后,所有對(duì)該資源的訪問(wèn)都會(huì)被直接拒絕,直到過(guò)了指定的時(shí)間窗口之后才重新恢復(fù)。

dubbo架構(gòu)

registry 注冊(cè)中心 模式zk實(shí)現(xiàn);服務(wù)注冊(cè)與發(fā)現(xiàn);
provider 服務(wù)提供者,發(fā)布服務(wù)到注冊(cè)中心
consumer 服務(wù)消費(fèi)方,從服務(wù)中心獲取已經(jīng)注冊(cè)的服務(wù)列表
container 服務(wù)容器 tomcat等
monitor dubbo監(jiān)控中心,做一些服務(wù)監(jiān)控,統(tǒng)計(jì)功能

dubbo支持哪些協(xié)議

dubbo 缺省協(xié)議 采用單一長(zhǎng)連接和NIO異步通訊 適合于小數(shù)據(jù)量大并發(fā)的服務(wù)調(diào)用 以及服務(wù)消費(fèi)者機(jī)器數(shù)遠(yuǎn)大于服務(wù)提供者機(jī)器數(shù)的情況;hessian二進(jìn)制序列化;mina通訊
rmi 采用JDK標(biāo)準(zhǔn)的 阻塞式短連接和JDK標(biāo)準(zhǔn)序列化
hessian 用于集成 Hessian 的服務(wù),Hessian 底層采用 Http 通訊,采用 Servlet 暴露服務(wù),Dubbo 缺省內(nèi)嵌 Jetty 作為服務(wù)器實(shí)現(xiàn)
http 多連接;短鏈接;json序列化;http傳輸
webservice 基于 WebService 的遠(yuǎn)程調(diào)用協(xié)議;http;多連接;短鏈接;SOAP文本序列化
thrift
memcached 基于 memcached實(shí)現(xiàn)的 RPC 協(xié)議
redis 基于 Redis實(shí)現(xiàn)的 RPC 協(xié)議
rest 基于標(biāo)準(zhǔn)的Java REST API

dubbo協(xié)議優(yōu)缺點(diǎn)

采用單一長(zhǎng)連接和NIO異步通訊 適合于小數(shù)據(jù)量大并發(fā)的服務(wù)調(diào)用 以及服務(wù)消費(fèi)者機(jī)器數(shù)遠(yuǎn)大于服務(wù)提供者機(jī)器數(shù)的情況;hessian二進(jìn)制序列化;mina通訊
不適合傳送大數(shù)據(jù)量的服務(wù),比如傳文件,傳視頻等,除非請(qǐng)求量很低

dubbo協(xié)議為什么不能傳大包

因dubbo協(xié)議采用單一長(zhǎng)連接,如果每次請(qǐng)求的數(shù)據(jù)包大小為500KByte,假設(shè)網(wǎng)絡(luò)為千兆網(wǎng)卡(1024Mbit=128MByte),每條連接最大7MByte(不同的環(huán)境可能不一樣,供參考),單個(gè)服務(wù)提供者的TPS(每秒處理事務(wù)數(shù))最大為:128MByte / 500KByte = 262。單個(gè)消費(fèi)者調(diào)用單個(gè)服務(wù)提供者的TPS(每秒處理事務(wù)數(shù))最大為:7MByte / 500KByte = 14

dubbo協(xié)議使用單鏈接好處

減少握手;在高QPS場(chǎng)景下,短鏈接有可能壓垮服務(wù)

dubbo中的SPI機(jī)制(自如1)

依靠SPI機(jī)制實(shí)現(xiàn)插件化功能,將所有的功能組件做成基于SPI實(shí)現(xiàn),提供了很多可以直接使用的擴(kuò)展點(diǎn),實(shí)現(xiàn)了面向功能進(jìn)行拆分的對(duì)擴(kuò)展開放的架構(gòu)。

Java中的SPI Classpath下的META-INF/services/創(chuàng)建一個(gè)以服務(wù)接口命名的文件,文件里面記錄的是此jar包提供的具體實(shí)現(xiàn)類的全限定名。JVM會(huì)在啟動(dòng)的時(shí)候掃描這個(gè)目錄,進(jìn)行加載
全部加載;沒(méi)有緩存;數(shù)據(jù)庫(kù)的driver

META-INF/services/ 目錄:該目錄下的 SPI 配置文件是為了用來(lái)兼容 Java SPI
META-INF/dubbo/ 目錄:該目錄存放用戶自定義的 SPI 配置文件
META-INF/dubbo/internal/ 目錄:該目錄存放 Dubbo 內(nèi)部使用的 SPI 配置文件

ExtensionLoader.getExtensionLoader 根據(jù)接口獲取其特有的自定義類加載器
ExtensionLoader.getExtension(name) 先讀Holder緩存,沒(méi)有創(chuàng)建一個(gè)holder,然后創(chuàng)建實(shí)例,先獲取類原信息,包含包裝等信息,先讀實(shí)例緩存,這里的實(shí)例緩存沒(méi)有經(jīng)過(guò)包裝,如果沒(méi)有進(jìn)行反射創(chuàng)建,然后執(zhí)行包裝,然后放入holder返回

@SPI 標(biāo)記一個(gè)接口需要被發(fā)現(xiàn)
@Wrapper 標(biāo)記這是一個(gè)包裝類 實(shí)現(xiàn)AOP
@Adaptive 標(biāo)記這是一個(gè)需要自適應(yīng)的方法

injectExtension發(fā)生在getExtension階段 IOC,拿出所有需要帶有set的method,獲取屬性名,從ObjectFactory中拿,ObjectFactory也是一個(gè)通過(guò)SPI發(fā)現(xiàn)的組件

ExtensionLoader是核心,靜態(tài)Map維護(hù)了所有class的ExtensionLoader,通過(guò)每個(gè)class的ExtensionLoader獲取對(duì)應(yīng)name的實(shí)例

dubbo自適應(yīng)擴(kuò)展

自適應(yīng)擴(kuò)展指的是不需要自己顯示調(diào)用ExtensionLoader.getExtension(name),而是通過(guò)一個(gè)ExtensionLoader.getAdaptiveExtension()獲取一個(gè)自適應(yīng)的實(shí)現(xiàn)類;
自適應(yīng)實(shí)現(xiàn)類是根據(jù)接口類方法上的@Adaptive進(jìn)行標(biāo)記,獲取自適應(yīng)實(shí)現(xiàn)時(shí)通過(guò)javaassist動(dòng)態(tài)將ExtensionLoader.getExtension(name)代碼寫到class文件中,并編譯后或?qū)嵗?br> name來(lái)自于參數(shù)中URL對(duì)象,所以adaptive方法參數(shù)中必須包含URL參數(shù);
未被Adaptive修飾的方法被調(diào)用會(huì)拋出notsupport異常
adaptive未設(shè)置value 按接口生成名獲取 駝峰改成.
adaptive設(shè)置一個(gè)value 從url獲取對(duì)應(yīng)參數(shù)
adaptive設(shè)置多個(gè)value 從后往前 每一個(gè)都是上一個(gè)的默認(rèn)值

adaptive實(shí)例有點(diǎn)像門面模式

@Adaptive修飾實(shí)現(xiàn)類,會(huì)直接將這個(gè)類當(dāng)做一個(gè)自適應(yīng)實(shí)現(xiàn)

dubbo SPI 的AOP

通過(guò)Wrapper實(shí)現(xiàn),在SPI文件內(nèi),并且包含傳入自身接口的構(gòu)造放放,將被視為一個(gè)包裝類;
沒(méi)有被Wrapper注解修飾,或者通過(guò)Wrapper上參數(shù)匹配或者違背派出的包裝類,在實(shí)現(xiàn)類被獲取時(shí)通過(guò)構(gòu)造方法包裝

dubbo與springcloud的區(qū)別

dubbo本身是一個(gè)RPC框架,基于RPC服務(wù)擴(kuò)展了周邊一系列功能,服務(wù)注冊(cè)與發(fā)現(xiàn),路由,負(fù)載均衡;
springcloud是一個(gè)微服務(wù)生態(tài),內(nèi)容比dubbo多很多,消息總線,配置中心,網(wǎng)關(guān)等

dubbo中的服務(wù)暴露

coding通過(guò)@DubboService標(biāo)記一個(gè)接口實(shí)現(xiàn)類需要被暴露
在Spring refresh階段執(zhí)行BeanFactoryPostProcessor ServiceClassPostProcessor掃描被DubboService修飾的類 處理成ServiceBeanDefinition注冊(cè)到BeanFactory
DubboBootstrapApplicationListener 在spring finishRefresh階段啟動(dòng)執(zhí)行所有ServiceBean.export對(duì)象的暴露
暴露本地服務(wù)(提供給本地服務(wù)調(diào)用),通過(guò)代理生成Invoker,經(jīng)過(guò)協(xié)議處理包裝成Exporter,注冊(cè)到注冊(cè)中心

dubbo中的服務(wù)發(fā)現(xiàn)

coding中通過(guò)@DubboReference標(biāo)記一個(gè)接口需要遠(yuǎn)程服務(wù),可以選擇實(shí)時(shí)注入,或者延時(shí)注入
在外部類Bean加載,populateBean事,執(zhí)行ReferenceAnnotationBeanPostProcessor,創(chuàng)建一個(gè)ReferenceBean注入,ReferenceBean是一個(gè)FactoryBean

dubbo中服務(wù)調(diào)用過(guò)程

dubbo中的容錯(cuò)

fastover 請(qǐng)求失敗,換一個(gè)節(jié)點(diǎn)重試,默認(rèn)1次
fastfail 請(qǐng)求失敗,返回失敗
全發(fā)一次成功一個(gè)就行
失敗了就返回空 記錄日志

seata支持哪些模式

支持at、tcc、saga、xa

AT模式 攔截用戶sql,解析之后找到對(duì)應(yīng)修改行,進(jìn)行快照;如果回滾,就使用快照數(shù)據(jù),如果提交,就刪除快照即可

Feign

Feign是Netflix開發(fā)的聲明式、模板化的HTTP客戶端, Feign可以幫助我們更快捷、優(yōu)雅地調(diào)用HTTP API。
Feign本身是一個(gè)RPC框架,依賴注冊(cè)中心的服務(wù)發(fā)現(xiàn)與注冊(cè),封裝了Ribbon和Hystrix也就是客戶端負(fù)載均衡以及服務(wù)容錯(cuò)保護(hù)
Spring Cloud對(duì)Feign進(jìn)行了增強(qiáng),使Feign支持了Spring MVC注解,并整合了Ribbon和Eureka,從而讓Feign的使用更加方便。
Spring Cloud Feign是基于Netflix feign實(shí)現(xiàn),整合了Spring Cloud Ribbon和Spring Cloud Hystrix,除了提供這兩者的強(qiáng)大功能外,還提供了一種聲明式的Web服務(wù)客戶端定義的方式。

Feign原理簡(jiǎn)述

啟動(dòng)時(shí),程序會(huì)進(jìn)行包掃描,掃描所有包下所有@FeignClient注解的類,并將這些類注入到spring的IOC容器中。當(dāng)定義的Feign中的接口被調(diào)用時(shí),通過(guò)JDK的動(dòng)態(tài)代理來(lái)生成RequestTemplate。
RequestTemplate中包含請(qǐng)求的所有信息,如請(qǐng)求參數(shù),請(qǐng)求URL等。
RequestTemplate聲場(chǎng)Request,然后將Request交給client處理,這個(gè)client默認(rèn)是JDK的HTTPUrlConnection,也可以是OKhttp、Apache的HTTPClient等。
最后client封裝成LoadBaLanceClient,結(jié)合ribbon負(fù)載均衡地發(fā)起調(diào)用。

什么是netty

netty是一個(gè)基于nio的客戶、服務(wù)器端編程框架,提供異步的,事件驅(qū)動(dòng)的網(wǎng)絡(luò)應(yīng)用程序框架和工具,可以快速開發(fā)高可用的客戶端和服務(wù)器。
netty是基于nio的,它封裝了jdk的nio,讓我們使用起來(lái)更加方法靈活。
并發(fā)高,傳輸快,封裝好

javaNIO模式 buffer channel selector

netty架構(gòu)

BootStrap、ServerBootStrap 啟動(dòng)引導(dǎo)類,通過(guò)鏈?zhǔn)秸{(diào)用串聯(lián)各個(gè)組件
Future\ChannelFuture Netty中所有IO操作都是異步的,這里的異步指使用多線程處理事件,需要注冊(cè)Future獲取結(jié)果
Channel 通訊組件,用于執(zhí)行網(wǎng)絡(luò)操作
Selector 基于Selector對(duì)象實(shí)現(xiàn)IO多路復(fù)用,一個(gè)S線程可以監(jiān)聽(tīng)多個(gè)Channel事件,
NioEventLoop 本質(zhì)上是一個(gè)單線程線程池,IO任務(wù)有processSelectedKeys觸發(fā),非IO任務(wù)有runAllTasks觸發(fā)
NioEventLoopGroup 管理eventloop的生命周期,也是一個(gè)線程池,每個(gè)線程負(fù)責(zé)處理一個(gè)Channel上的事件
ChannelHandler 處理IO事件,將操作轉(zhuǎn)發(fā)到ChannelPipeline中
ChannelHandlerContext 用于傳遞Channel上下文信息關(guān)聯(lián)一個(gè)ChannelHandler對(duì)象
ChannelPipeline 保存ChannerlHandler的list,用于處理或攔截Channerl的入站和出站事件,一個(gè)Channel包含一個(gè)ChannerlPipeline

netty線程模式

基于reactor
單reactor單線程
單reactor多線程
多reactor多線程 BossNioEventGroup(mainReactor)負(fù)責(zé)處理所有accept事件,注冊(cè)到acceptor中,建立同道channel注冊(cè)到WorkerNioEventGroup(sunReactor),sunReactor負(fù)責(zé)處理他管理的channel的read write事件,和處理pipeline任務(wù)

netty5為什么被廢棄

主要是使用了ForkJoinPool,增加復(fù)雜度,也沒(méi)提升多少性能;aio技術(shù)不大成熟;作者好像沒(méi)啥時(shí)間

Elasticsearch

Elasticsearch 是一個(gè)分布式可擴(kuò)展的實(shí)時(shí)搜索和分析引擎,一個(gè)建立在全文搜索引擎 Apache Lucene(TM) 基礎(chǔ)上的搜索引擎.
全文搜索功能,
分布式實(shí)時(shí)文件存儲(chǔ),并將每一個(gè)字段都編入索引,使其可以被搜索。
實(shí)時(shí)分析的分布式搜索引擎。
可以擴(kuò)展到上百臺(tái)服務(wù)器,處理PB級(jí)別的結(jié)構(gòu)化或非結(jié)構(gòu)化數(shù)據(jù)。

倒排索引

正向索引就是我們?yōu)橛涗浬洗蛏细鞣N標(biāo)簽,比如記錄行1 name age等
倒排索引 我們?yōu)槊總€(gè)name記錄包含它的記錄行,
es使用的是倒排索引
mysql的fullindex

ES的分布式(雪球1)

ES集群中每個(gè)節(jié)點(diǎn)內(nèi)部都有很多分片,這些不同節(jié)點(diǎn)中的分片互為主備;
保存數(shù)據(jù)時(shí),根據(jù)ID確定數(shù)據(jù)應(yīng)當(dāng)存放的分片,找到主分片對(duì)應(yīng)的節(jié)點(diǎn),轉(zhuǎn)發(fā)消息;
執(zhí)行成功之后,主分片向副分片進(jìn)行同步

ES的索引(雪球1)

ES使用倒排索引技術(shù)
term index -> term dictionary -> Posting List(維護(hù)文檔ID,權(quán)重等信息)
對(duì)term dictionary使用二級(jí)索引快速定位到對(duì)應(yīng)的term

index 對(duì)應(yīng)databases 索引只是一個(gè) 邏輯命名空間,它指向一個(gè)或多個(gè)分片(shards),內(nèi)部用Apache Lucene實(shí)現(xiàn)索引中數(shù)據(jù)的讀寫
type 對(duì)應(yīng)scheme 每個(gè)文檔在ElasticSearch中都必須設(shè)定它的類型。文檔類型使得同一個(gè)索引中在存儲(chǔ)結(jié)構(gòu)不同文檔時(shí),只需要依據(jù)文檔類型就可以找到對(duì)應(yīng)的參數(shù)映射(Mapping)信息,方便文檔的存取
document 對(duì)應(yīng)rows 是可以被索引的基本單位
field 對(duì)應(yīng)column

ES的中文分詞器

hanlp ik

ES中Term index(雪球1)

字典樹,專門處理字符串匹配,不包含所有term,包含所有term公共前綴,快速定位 term dictionary 的某個(gè)offset;
term index 在內(nèi)存中是以 FST(finite state transducers)的數(shù)據(jù)結(jié)構(gòu)保存

ES中term dictionary

在磁盤上面是分 block 保存的,一個(gè) block 內(nèi)部利用公共前綴壓縮,比如都是 Ab 開頭的單詞就可以把 Ab 省去

什么是Mybatis

半orm框架,aop封裝jdbc,connection、preparestatement、resultset映射,只需要關(guān)注sql,減少jdbc代碼開發(fā)量
優(yōu)點(diǎn):減少代碼開發(fā)量,可以與spring集成
缺點(diǎn):可移植性差,不是面向?qū)ο?/p>

Mybatis緩存

一級(jí)緩存 sqlsession級(jí)別,內(nèi)存緩存,默認(rèn)開啟,一次會(huì)話沒(méi)有update多次查詢返回緩存結(jié)果,update就刷新
二級(jí)緩存 自己命名作用于,可以自定義實(shí)現(xiàn),默認(rèn)不開啟

虛擬地址空間、用戶空間、內(nèi)核空間

內(nèi)存分頁(yè) 節(jié)約、提高效率,內(nèi)存拆成一塊塊4k 的page
虛擬地址空間 多任務(wù)OS,進(jìn)程運(yùn)行在各自的虛擬內(nèi)存中,為了隔離;進(jìn)程通過(guò)pagetable映射到物理內(nèi)存;可以先建立虛擬地址空間并不映射物理內(nèi)存,用的時(shí)候再映射物理內(nèi)存
虛擬地址空間分為用戶空間和內(nèi)核空間 linux3:1
內(nèi)核空間 為了系統(tǒng)安全 os強(qiáng)制用戶進(jìn)程不能直接操作內(nèi)核,內(nèi)核也需要內(nèi)存,與用戶進(jìn)程隔離,單獨(dú)使用內(nèi)核空間
linux啟動(dòng)時(shí),將內(nèi)核程序加載到物理內(nèi)存的內(nèi)核空間上運(yùn)行,為了能讓用戶進(jìn)程使用內(nèi)核來(lái)完成系統(tǒng)調(diào)用,將虛擬地址空間的內(nèi)核空間映射到物理的內(nèi)核空間上
用戶態(tài) 程序運(yùn)行在用戶空間,屬于用戶態(tài)
內(nèi)核態(tài) 程序畸形系統(tǒng)調(diào)用,進(jìn)入內(nèi)核空間運(yùn)行,處于內(nèi)核態(tài)
用戶切換到內(nèi)核態(tài):系統(tǒng)調(diào)用 異常 外圍設(shè)備中斷

Memcached集群(雪球1)

memcached本身并沒(méi)有提供集群部署的方案,一般部署多臺(tái)實(shí)例,在客戶端采用一致性hash的方案,選擇對(duì)應(yīng)的實(shí)例進(jìn)行通訊。必須知道所有實(shí)例地址,本地shard規(guī)則需要統(tǒng)一維護(hù)。
或者原則一些開源的代理方案,
mcrouter facebook的成熟案例;功能強(qiáng)大,支持Memcache實(shí)例分組、實(shí)例復(fù)制功能,實(shí)例宕機(jī)后可自動(dòng)踢出;一般用于ubuntu平臺(tái),在centos上安裝較復(fù)雜
Magent代理

Memcached線程模型

一個(gè)master多個(gè)worker線程
每個(gè)woker線程使用一個(gè)libevent對(duì)象封裝,包含線程信息和conn隊(duì)列,每個(gè)請(qǐng)求進(jìn)來(lái)master為其封裝一個(gè)conn對(duì)象,選擇對(duì)應(yīng)的worker線程

Memcache內(nèi)存模型

啟動(dòng)時(shí)創(chuàng)建 slabclass_t數(shù)組,slabclass_t數(shù)組維護(hù)一組slab對(duì)象,定義slab內(nèi)部chunk大小,slab數(shù)組,slab數(shù)量,slab由一組page構(gòu)成,一個(gè)page最大1k~128m,一個(gè)page包含相同大小的一組chunk;
每個(gè)slab對(duì)象按照slabclass_t定義的chunk大小進(jìn)行分割,chunk是一個(gè)固定大小的物理存儲(chǔ)單元,有可能造成空間浪費(fèi),
item是存儲(chǔ)在chunk的邏輯數(shù)據(jù),維護(hù)雙向指針、key、value、time等信息
數(shù)據(jù)寫入時(shí),根據(jù)大小(超過(guò)1m,直接丟棄)找到對(duì)應(yīng)的slabclass_t,遍歷slab對(duì)象找到有空閑的chunk,進(jìn)行數(shù)據(jù)存儲(chǔ);如果沒(méi)有空閑就創(chuàng)建一個(gè)新的salb,如果內(nèi)存不夠執(zhí)行LRU策略
Slab Allocator分配內(nèi)存 每個(gè)slabclass_t都會(huì)分配一個(gè)1M大小的slab,slab又會(huì)被切分為N個(gè)小的內(nèi)存塊chunk,這個(gè)小的內(nèi)存塊的大小取決于slabclass_t結(jié)構(gòu)上的size的大小。
grow factor調(diào)優(yōu)

Memcache中的LRU

當(dāng)最終沒(méi)有足夠內(nèi)存分配給Item時(shí),memcache將執(zhí)行LRU來(lái)獲取空間。首先從slab的尾部LRU鏈表tail[]開始搜索,檢查該鏈表中是否有無(wú)效item,如果有則清除掉,將該空間用于存儲(chǔ)新的Item,此操作最多嘗試50次。如果沒(méi)有無(wú)效Item,則看是否有開啟強(qiáng)制淘汰,如果開啟了,則無(wú)條件清除最后一個(gè)Item,即使該Item被設(shè)置成永久有效。如果沒(méi)有開啟,則拋出Out Of Memory錯(cuò)誤。

Memcached總結(jié)

1、MemCache中可以保存的item數(shù)據(jù)量是沒(méi)有限制的,只要內(nèi)存足夠
2、MemCache單進(jìn)程在32位機(jī)中最大使用內(nèi)存為2G,這個(gè)之前的文章提了多次了,64位機(jī)則沒(méi)有限制
3、Key最大為250個(gè)字節(jié),超過(guò)該長(zhǎng)度無(wú)法存儲(chǔ)
4、單個(gè)item最大數(shù)據(jù)是1MB,超過(guò)1MB的數(shù)據(jù)不予存儲(chǔ)
5、MemCache服務(wù)端是不安全的,比如已知某個(gè)MemCache節(jié)點(diǎn),可以直接telnet過(guò)去,并通過(guò)flush_all讓已經(jīng)存在的鍵值對(duì)立即失效
6、不能夠遍歷MemCache中所有的item,因?yàn)檫@個(gè)操作的速度相對(duì)緩慢且會(huì)阻塞其他的操作
7、MemCache的高性能源自于兩階段哈希結(jié)構(gòu):第一階段在客戶端,通過(guò)Hash算法根據(jù)Key值算出一個(gè)節(jié)點(diǎn);第二階段在服務(wù)端,通過(guò)一個(gè)內(nèi)部的Hash算法,查找真正的item并返回給客戶端。從實(shí)現(xiàn)的角度看,MemCache是一個(gè)非阻塞的、基于事件的服務(wù)器程序
8、MemCache設(shè)置添加某一個(gè)Key值的時(shí)候,傳入expiry為0表示這個(gè)Key值永久有效,這個(gè)Key值也會(huì)在30天之后失效

MongoDB

MongoDB 是由C++語(yǔ)言編寫的,是一個(gè)基于分布式文件存儲(chǔ)的開源數(shù)據(jù)庫(kù)系統(tǒng)。
MongoDB 將數(shù)據(jù)存儲(chǔ)為一個(gè)文檔,數(shù)據(jù)結(jié)構(gòu)由鍵值(key=>value)對(duì)組成。MongoDB文檔類似于JSON對(duì)象。字段值可以包含其他文檔,數(shù)組及文檔數(shù)組。

MongoDB速度快的原因

寫:內(nèi)存映射技術(shù) - 寫入數(shù)據(jù)時(shí)候只要在內(nèi)存里完成就可以返回給應(yīng)用程序,保存到硬體的操作則在后臺(tái)異步完成
讀:內(nèi)存緩存常用數(shù)據(jù),文檔模式數(shù)據(jù)都在一起,磁盤順序讀寫

分布式集群擴(kuò)展

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 螞蟻金服研發(fā)面經(jīng) 螞蟻金服中間件 螞蟻財(cái)富 研發(fā)工程師 之前面了阿里中間件的提前批,不過(guò)沒(méi)走流程。同期還面了螞蟻中...
    Java_蘇先生閱讀 971評(píng)論 0 0
  • nginx的請(qǐng)求轉(zhuǎn)發(fā)算法,如何配置根據(jù)權(quán)重轉(zhuǎn)發(fā) 負(fù)載均衡策略:內(nèi)置策略:輪詢(默認(rèn))、加權(quán)輪詢(處理1次連接則權(quán)重...
    星冉子閱讀 516評(píng)論 0 1
  • 16宿命:用概率思維提高你的勝算 以前的我是風(fēng)險(xiǎn)厭惡者,不喜歡去冒險(xiǎn),但是人生放棄了冒險(xiǎn),也就放棄了無(wú)數(shù)的可能。 ...
    yichen大刀閱讀 7,594評(píng)論 0 4
  • 公元:2019年11月28日19時(shí)42分農(nóng)歷:二零一九年 十一月 初三日 戌時(shí)干支:己亥乙亥己巳甲戌當(dāng)月節(jié)氣:立冬...
    石放閱讀 7,389評(píng)論 0 2
  • 今天上午陪老媽看病,下午健身房跑步,晚上想想今天還沒(méi)有斷舍離,馬上做,衣架和旁邊的的布衣架,一看亂亂,又想想自己是...
    影子3623253閱讀 3,056評(píng)論 3 8

友情鏈接更多精彩內(nèi)容