1 為什么使用分布式系統(tǒng)玉凯?
單體式架構(gòu)風(fēng)險高奋渔,每次需要完全更新,容易引來大規(guī)模問題壮啊,不夠穩(wěn)定;而分布式系統(tǒng)易于擴展撑蒜,根據(jù)業(yè)務(wù)場景進拆分歹啼,發(fā)布的可以是單個服務(wù),對已有功能影響較凶ぁ狸眼;即使有業(yè)務(wù)出現(xiàn)問題,也易于排查浴滴,而且有些模塊訪問量高拓萌,有些訪問量低,可以針對性的進行擴展升略,訪問量高的部署在多個機器上微王。同樣系統(tǒng)會越來越復(fù)雜,迭代成本高品嚣,版本維護復(fù)雜炕倘,還有cap問題,數(shù)據(jù)一致性問題等翰撑,所有需要辯證看待罩旋。
2 rpc怎么理解?
rpc顧名思義,就是調(diào)用其他機器上的接口如同調(diào)用本地接口一樣涨醋,那么需要知道接口的ip地址瓜饥,端口,服務(wù)名浴骂,這些東西被統(tǒng)一管理在注冊中心乓土,調(diào)用方去注冊中心查要是用服務(wù),然后去調(diào)用
3 注冊中心掛了靠闭,服務(wù)之間是否還能互相調(diào)用帐我?
這個要分情況看待,首先注冊中心可以集群部署愧膀,有相應(yīng)的備份拦键,其次如果數(shù)據(jù)庫掛了,注冊中心有緩存檩淋,如果注冊中心服務(wù)掛了芬为,那么對應(yīng)的服務(wù)也都有服務(wù)緩存,只要相應(yīng)的服務(wù)沒有下線就可以繼續(xù)使用蟀悦。
4 CAP
提升可用性A 一般通過增加緩存媚朦,增加服務(wù)器,引入消息隊列
提升容錯性P 增加集群部署日戈,都有備份询张,容災(zāi)備份
提高數(shù)據(jù)一致性C
分布式數(shù)據(jù)庫就是犧牲一致性,滿足高可用性和容錯性浙炼,尤其是要求高可用性份氧,解決高可用性主要就是備胎要多
5 負(fù)載均衡策略
應(yīng)用及負(fù)載均衡:
輪詢策略,隨機策略 加權(quán)策略
多個方式配合使用 輪詢加權(quán)等
相應(yīng)時間+權(quán)重策略
網(wǎng)關(guān)級負(fù)載策略:
gateway
nginx 反向代理 請求先轉(zhuǎn)發(fā)到nginx上面然后nginx再進行轉(zhuǎn)發(fā)
6 服務(wù)熔斷
熔斷器根據(jù)服務(wù)調(diào)用失敗率來判斷弯屈,如果一個服務(wù)短時間內(nèi)失敗率很高就被判定為不可用蜗帜,就會斷開服務(wù),防止發(fā)生更嚴(yán)重的問題(雪崩)资厉;熔斷器有重試機制厅缺,5秒內(nèi),如果失敗率降低就會關(guān)掉熔斷機制宴偿,恢復(fù)服務(wù)湘捎;熔斷往往和降級一起使用,一旦發(fā)生熔斷酪我,就會使用一些降級方法比如getfallback(提示用戶稍后重試等)消痛,比如redis服務(wù)掛了, 可以使用備胎用其他資源代替服務(wù)(ES elasticsearch都哭,或者本地緩存 guava)開源熔斷器 hystrix sentinel等
7 高并發(fā)問題:
線程隔離:主要原理是不通的方法使用不同的線程池進行隔開秩伞,防止所有的方法相互影響逞带,沒有可調(diào)用線程,防止訪問量大的方法占用所有線程
信號量隔離: 線程池隔離比較重纱新,適用于查詢量比較大展氓,計算比較復(fù)雜的情況;信號量隔離比較輕量化脸爱,適合計算量小的業(yè)務(wù)遇汞,輕量化查詢等,簿废;也適用于網(wǎng)關(guān)層使用空入,在網(wǎng)關(guān)層直接用信號量對流量進行控制
8 消息隊列
原理: 消費者生產(chǎn)者模式;
用處:可以用來異步處理 流量削峰 應(yīng)用解耦
問題:雙刃劍 帶來的復(fù)雜度翻一倍 族檬,會帶來三個方面的問題:可用性問題歪赢,一致性問題,復(fù)雜性問題
如何處理重復(fù)消息单料?
什么情況會產(chǎn)生重復(fù)消息:1 比如生產(chǎn)者發(fā)給broker的過程中埋凯,broker寫入之后,如果broker的響應(yīng)慢了扫尖,觸發(fā)了了生產(chǎn)者的消息補償那么就會導(dǎo)致消息重復(fù)白对;2在消費者消費階段,如果消費者正確處理完消息换怖,需要更新consumeroffset甩恼,但是還沒來得及更新,消費者掛了沉颂, 那么新來一個消費者會重復(fù)消費一次同一消息
解決辦法就是對接口做冪等設(shè)計
如何保證消息沒有重復(fù)消費媳拴?
在發(fā)送方為了防止消息丟失,會做消息補償兆览,消費方響應(yīng)超時,網(wǎng)絡(luò)抖動塞关,mq掛了等抬探,導(dǎo)致發(fā)送方長時間拿不到消息的回復(fù),就會嘗試重發(fā)一遍消息:解決辦法是做好接口的冪等設(shè)計帆赢;
冪等設(shè)計方案:1進行約束控制小压,在數(shù)據(jù)庫層面做unique索引,在redis層面做sennx約束控制椰于,來進行唯一性控制怠益;2設(shè)置前置條件,處理之前加一個查詢瘾婿,查看是否操作成功蜻牢,另外這個查詢需要加分布式鎖烤咧,防止有并發(fā)問題,或者利用數(shù)據(jù)庫版本號進行對比查詢抢呆;3 消息設(shè)置全局id(比較復(fù)雜)煮嫌,可以多個方案配合使用
怎么處理消息丟失的情況?
通過三個階段保證抱虐,分別是消息--->
生產(chǎn)階段:消息確認(rèn)機制昌阿,保證消息發(fā)送到broker 階段,會用到一些消息補償機制
存儲階段:使用持久化存儲機制(除非是網(wǎng)絡(luò)故障等恳邀,暴力性問題)
消費階段:通過消息確認(rèn)機制懦冰,會用到消息補償機制
消息丟失的兜底方案:1 使用攔截器(用到aop原理)記錄版本號,消息消費時查看是否版本號連續(xù)來做一次double check 2 使用狀態(tài)碼谣沸,定時(cron)檢測訂單或者事件有沒有正常變化刷钢,從而使用一些處理手段,也是一種double check方案
如何保證消息不丟失鳄抒?
三個方面:1生產(chǎn)者處理好各類異常問題闯捎,比如callback中的trycatch處理,做好上報许溅; 2存儲階段需要注意先落盤再給生產(chǎn)者響應(yīng)瓤鼻; 3 消費階段,在消費者執(zhí)行完業(yè)務(wù)邏輯贤重,在給broker相應(yīng)
怎么保證消息傳遞的順序性茬祷?
全局有序以及局部有序,絕大多數(shù)場景只需要局部有序
將有關(guān)聯(lián)關(guān)系的消息放到同一個隊列中去并蝗,保證消息消費的順序性祭犯,要注意多線程問題
消息隊列,消費積壓如何解決滚停?
如果是生產(chǎn)者的問題沃粗,那么利用限流熔斷策略,減少源頭產(chǎn)生的消息數(shù)量键畴,比如令牌通算法
如果是消費端的問題最盅,那么加快消費速度,優(yōu)化代碼邏輯解決bug起惕,如果瓶頸在數(shù)據(jù)庫涡贱,那就先存redis,等到不忙再做持久化存儲惹想,可以做批處理增加速度问词,最后可以考慮擴容;
死信隊列:指消息隊列中無法消費的消息嘀粱,比如過期的消息會被放到死信隊列中激挪;死信隊列的另一個用處是可以用來處理延遲消息
消息隊列中的事務(wù)性問題辰狡?
相當(dāng)于有一個協(xié)調(diào)者保證所有消息全部成功或者全部失敗
協(xié)調(diào)者可以采用tcc機制 try confirm commit
用來解決一致性問題;比如用戶下單的場景下:先發(fā)送一個隱藏的消息(也叫半消息灌灾,在broker 中只是一個日志記錄搓译,還沒有完全存儲下來,rocktmq中叫commitlog)锋喜,如果用戶下單成功(生產(chǎn)端業(yè)務(wù)執(zhí)行成功之后)些己,再從commitlog中撈出來,該消息轉(zhuǎn)為普通消息嘿般,再由broker將消息轉(zhuǎn)到消費端進行消費 否則段标,回滾所有操作,刪除該隱藏消息炉奴。
消息隊列掛了逼庞,事務(wù)如何處理?
利用數(shù)據(jù)庫的事務(wù)機制瞻赶,使用本地數(shù)據(jù)表赛糟,把本地事務(wù)操作和本地消息插入做成同一個事務(wù);同時后臺起一個線程關(guān)注本地數(shù)據(jù)表每條數(shù)據(jù)的狀態(tài)砸逊,進行相應(yīng)的回滾或者重試操作
剛性事務(wù)和柔性事務(wù)璧南?
剛性是指強一致性,任何時間點所有節(jié)點都是一致性的师逸,比如xa司倚;問題是會有性能的影響,因為需要鎖住所有的資源篓像,高并發(fā)場景使用不多
柔性是指不要求強一致性动知,要求最終一致性,不追求所有節(jié)點在所有時間都保持一致员辩,但是最終要保持一致盒粮。
消息隊列選型? kafka rocketmq rabbitmq
互聯(lián)網(wǎng)奠滑,電商平臺 低時延可以選擇rocketmq java實現(xiàn)拆讯,每秒幾十萬級處理量
處理大批量數(shù)據(jù)同步 離線計算 對延遲有一定包容性 兼容性好 選擇kafka
如何設(shè)計一個消息隊列?
需要考慮消費者养叛,生產(chǎn)者,存儲宰翅,路由弃甥,分發(fā),消息類型汁讼,保障機制
如何理解消息隊列的推push pull拉模式
一般生產(chǎn)者與broker之間都是推模式淆攻;
消費者與broker之間可以使用推模式也可以使用拉模式阔墩;
rabbitmq默認(rèn)是推模式,優(yōu)點是實時性比較好瓶珊,也可能帶來消費堆積的問題
kafka rocketmq默認(rèn)采用拉模式啸箫,優(yōu)點是可以控制消費的消息數(shù)量,不易產(chǎn)生消息堆積伞芹,問題是實時性不夠高忘苛,解決辦法是長輪訓(xùn)方式,如果有消息就返回唱较,如果沒有沒有就等到超時扎唾,超時之后斷開連接,之后再重新連接
9 分布式數(shù)據(jù)庫——數(shù)據(jù)庫分庫分表
為什么要分庫分表南缓?
sql查詢變慢胸遇,單表數(shù)據(jù)達到1000w條以上,需要考慮分庫分表
水平拆分汉形,就是分表之后纸镊,可以減少寫操作的范圍,建立索引以及查詢的速度都會變快
分庫 就是一主多從讀寫分離
分庫分表可能帶來的問題概疆?
1) 不能join 一般使用數(shù)據(jù)冗余的策略解決逗威,多加一行重復(fù)的數(shù)劇
2)id自增不能使用數(shù)據(jù)庫自增序列了,需要使用uuid snowflake leaf redis的incre等
3)需要重新分表届案,需要重新刷盤
4)同步帶來的分布式事務(wù)的問題 主要使用tcc機制解決 也可以使用xa 開源框架seata bytetcc等
5)分頁查詢 需要根據(jù)分表策略以及查詢邏輯具體情況具體分析 提前復(fù)雜查詢邏輯庵楷,提前查詢好,做好緩存邏輯
6) 查詢優(yōu)化楣颠,將數(shù)據(jù)提前存儲到redis es等內(nèi)存數(shù)據(jù)庫中尽纽,提升查詢速度;
自增id序列如何處理童漩?
1)分表之后間隔遞增
2)使用redis的incre弄贿,有可能redis服務(wù)會掛,掛了之后可以使用aof繼續(xù)遞增
3)snowflake 雪花算法矫膨,公認(rèn)方案差凹,核心由三部分組成時間戳+機器+序號,可能存在的問題是時間回?fù)埽?br> 數(shù)據(jù)庫分庫之后的問題
分庫可以帶來數(shù)據(jù)庫的讀寫分離侧馅,一主多從危尿,主庫可讀可寫,從庫只能讀馁痴,數(shù)據(jù)來源于主庫的同步
mysql 使用binlog進行主從同步谊娇,從庫有多個可以設(shè)置負(fù)載均衡策略
為什么禁止使用select *?
1)無法使用索引罗晕,會導(dǎo)致查詢性能很差济欢;
2)select * 比較耗時赠堵,會拖垮整個數(shù)據(jù)庫的查詢效率,阻塞所有的查詢線程法褥;
10 分布式事務(wù)
分布式主流的實現(xiàn)方案有兩種---->
1)xa協(xié)議茫叭,原理是兩階段提交,依賴數(shù)據(jù)庫本身的事務(wù)半等,事務(wù)開啟前揍愁,分布式事務(wù)管理器先詢問所有的數(shù)據(jù)庫是否準(zhǔn)備好,如果所有的都回復(fù)ok酱鸭,那么就執(zhí)行事務(wù)吗垮,如果有一個沒有回復(fù)ok那么就會滾事務(wù);缺點是效率不是很高
2)tcc 不依賴數(shù)據(jù)庫本身的事務(wù)凹髓,分為三個階段try confirm cancle烁登,try階段做檢測和資源預(yù)留;confirm階段做具體業(yè)務(wù)操作蔚舀,如果遇到錯誤就直接回滾饵沧,通過補償機制實現(xiàn)回滾操作;使用較廣泛
11 如何設(shè)計秒殺系統(tǒng)赌躺?
1)靜態(tài)資源 + 做好多級緩存(本地緩存+redis緩存)
2)前端頁面級限流狼牺,后端網(wǎng)關(guān)層做限流算法令牌桶,漏桶等礼患,規(guī)定周期放一定流量進來是钥,其他消息直接返回網(wǎng)絡(luò)繁忙等,開啟熔斷機制兜底
3)使用分布式鎖(redis zookper)做好庫存的原子扣減缅叠,或者使用數(shù)據(jù)庫的觸發(fā)器
12 分布式系統(tǒng)下的鑒權(quán)認(rèn)證方案
基于token方案悄泥,第一次認(rèn)證登錄生成token客戶端和服務(wù)端都存下來,客戶端每次請求都帶上肤粱,服務(wù)端存在redis里面
13 nginx如何實現(xiàn)高可用
nginx理論山支持5w并發(fā)鏈接
1)一般使用nginx+keep alive 弹囚,一主一從,如果主節(jié)點掛了领曼,把備用的nginx節(jié)點頂上來鸥鹉,缺點是,從服務(wù)器可能一直閑置庶骄,解決辦法是互為主備
2)集群部署毁渗,可以使用LVS,理論上可以支持幾十萬的并發(fā)請求 阿里的SLB負(fù)載均衡策略单刁,云服務(wù)器不支持虛擬ip灸异,硬件負(fù)載F5
14 分布式鎖
通過redis實現(xiàn)
如何解決死鎖問題
原因:加鎖之后各種原因?qū)е聸]有正常釋放鎖
解決:保證鎖正常釋放 1刪除鎖的key,需要注意是否是當(dāng)前線程加的鎖,判斷鎖是否被占用 使用lua腳本保證操作的原子性 2 設(shè)置過期時間 需要保證操作原子性
分布式鎖超過過期時間绎狭,需要增加守護線程(watch dog)輪詢業(yè)務(wù)是否處理完,沒有處理完給鎖續(xù)命
15 分布式場景在的調(diào)度框架
1)阿里云 schedulex
2)quarts
3)大眾點評徐雪里 xxl-job
4)當(dāng)當(dāng) elasticjob
5
5