前言
文本已收錄至個人GitHub倉庫,歡迎Star:
https://github.com/bin3923282...
種一棵樹最好的時間是十年前,其次是如今
Tips
面試指南系列,不少狀況下不會去深挖細節,是小六六以被面試者的角色去回顧知識的一種方式,因此我默認大部分的東西,做爲面試官的你,確定是懂的。前端
https://www.processon.com/vie...
上面的是腦圖地址java
叨絮
分佈式系統開發,微服務架構的一種主流實現方式,固然在面試中是必不可少的拉。mysql
而後下面是前面的文章彙總git
什麼是SpringBoot呢
簡而言之,從本質上來講,Spring Boot 就是 Spring,它作了那些沒有它你本身也會去作的 Spring Bean 配置。基於約定大於配置的一個理論github
說說SpringBoot的特色吧
- 開發基於 Spring 的應用程序很容易。
- Spring Boot 項目所需的開發或工程時間明顯減小,一般會提升總體生產力。
- Spring Boot 不須要編寫大量樣板代碼、XML 配置和註釋。
- Spring 引導應用程序能夠很容易地與 Spring 生態系統集成,如 Spring JDBC、Spring ORM、Spring Data、Spring Security 等。
- Spring Boot 遵循「執拗己見的默認配置」,以減小開發工做(默認配置能夠修改)。
- Spring Boot 應用程序提供嵌入式 HTTP 服務器,如 Tomcat 和 Jetty,能夠輕鬆地開發和測試 web 應用程序。(這點很贊!普通運行 Java 程序的方式就能運行基於 Spring Boot web 項目,省事不少)
說說@SpringBootApplication 這個註解吧
能夠看出大概能夠把 @SpringBootApplication 看做是 @Configuration、@EnableAutoConfiguration、@ComponentScan 註解的集合。根據 SpringBoot官網,這三個註解的做用分別是:web
- @EnableAutoConfiguration:啓用 SpringBoot 的自動配置機制
- @ComponentScan: 掃描被@Component (@Service,@Controller)註解的bean,註解默認會掃描該類所在的包下全部的類。
- @Configuration:容許在上下文中註冊額外的bean或導入其餘配置類。
-因此說 @SpringBootApplication 就是幾個重要的註解的組合,爲何要有它?固然是爲了省事,避免了咱們每次開發 Spring Boot 項目都要寫一些必備的註解。這一點在咱們平時開發中也 常常用到,好比咱們一般會提一個測試基類,這個基類包含了咱們寫測試所須要的一些基本的註解和一些依賴。面試
知道SpringBoot的鉤子函數嗎,如何對你項目的啓動和死亡作監控。
- 啓動的時候,好比CommandLineRunner 重寫它的run方法,就能在啓動的時候作一個鉤子函數,好比連接釘釘等
- 意外宕機也是能夠的, @PreDestroy 這個註解也能實現,在宕機以前回調這個方法,實現釘釘機器人等。
瞭解spring boot 中的spring factories 機制嗎?
Spring Factories.這種機制其實是仿照java中的SPI擴展機制實現的。spring
spring -core 包裏定義了SpringFactoriesLoader 類,這個類實現了檢索META-INF/spring.factories文件,並獲取指定接口的配置的功能。 在這個類中定義了兩個對外的方法:
-loadFactories 根據接口類獲取其實現類的實例,這個方法返回的是對象列表sql
- loadFactoryNames 根據接口獲取其接口類的名稱,這個方法返回的是類名的列表。
說說springBoot的自動配置原理吧
首先咱們知道SpringBoot項目的啓動註解@SpringBootApplication 中有一個@EnableAutoConfiguration,這個就是開啓springBoot的自動註冊機制
能夠看到,在@EnableAutoConfiguration註解內使用到了@import註解來完成導入配置的功能,而EnableAutoConfigurationImportSelector內部則是使用了SpringFactoriesLoader.loadFactoryNames方法進行掃描具備META-INF/spring.factories文件的jar包數據庫
最後再加上咱們的EnableAutoConfiguration 讀取咱們在配置文件中的文件就能夠實現自動配置了,就好比咱們的springboot Admin,咱們的client只要配置下配置文件就能成功了,緣由就是這個
上面這些都是Spring Boot中的自動配置相關類;在啓動過程當中會解析對應類配置信息。每一個Configuation類都定義了相關bean的實例化配置。都說明了哪些bean能夠被自動配置,什麼條件下能夠自動配置,並把這些bean實例化出來。若是咱們自定義了一個starter的話,也要在該starter的jar包中提供 spring.factories文件,而且爲其配置org.springframework.boot.autoconfigure.EnableAutoConfiguration對應的配置類。全部框架的自動配置流程基本都是同樣的,判斷是否引入框架,獲取配置參數,根據配置參數初始化框架相應組件
說說SpringBoot的啓動流程吧
其實這塊很大一部分和spring的啓動流程有重疊的,可是,咱們仍是從頭至尾來過一遍,當複習了。
SpringBoot的啓動主要是經過實例化SpringApplication來啓動的,啓動過程主要作了如下幾件事情:配置屬性、獲取監聽器,發佈應用開始啓動事件初、始化輸入參數、配置環境,輸出banner、建立上下文、預處理上下文、刷新上下文(加載tomcat容器)、再刷新上下文、發佈應用已經啓動事件、發佈應用啓動完成事件。
實例化SpringApplication時作了什麼
- 推斷WebApplicationType,主要思想就是在當前的classpath下搜索特定的類
- 搜索META-INF\spring.factories文件配置的ApplicationContextInitializer的實現類
- 搜索META-INF\spring.factories文件配置的ApplicationListenerr的實現類
- 推斷MainApplication的Class
SpringApplication的run方法作了什麼?
- 建立一個StopWatch並執行start方法,這個類主要記錄任務的執行時間
- 配置Headless屬性,Headless模式是在缺乏顯示屏、鍵盤或者鼠標時候的系統配置
- 在文件META-INF\spring.factories中獲取SpringApplicationRunListener接口的實現類EventPublishingRunListener,主要發佈SpringApplicationEvent
- 把輸入參數轉成DefaultApplicationArguments類
- 建立Environment並設置好比環境信息,系統熟悉,輸入參數和profile信息
- 打印Banner信息
- 建立Application的上下文,根據WebApplicationTyp來建立Context類,若是非web項目則建立AnnotationConfigApplicationContext,在構造方法中初始化AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner
- 在文件META-INF\spring.factories中獲取SpringBootExceptionReporter接口的實現類FailureAnalyzers
- 準備application的上下文
- 初始化ApplicationContextInitializer
- 執行Initializer的contextPrepared方法,發佈ApplicationContextInitializedEvent事件
- 若是延遲加載,在上下文添加處理器LazyInitializationBeanFactoryPostProcessor
- 執行加載方法,BeanDefinitionLoader.load方法,主要初始化了AnnotatedGenericBeanDefinition
- 執行Initializer的contextLoaded方法,發佈ApplicationContextInitializedEvent事件
- 刷新上下文(後文會單獨分析refresh方法),在這裏真正加載bean到容器中。若是是web容器,會在onRefresh方法中建立一個Server並啓動。
refresh方法 和spring的有點不一樣
srping中的onrefesh方法是空的,這個裏面是須要去加載web容器的如tomcat jetty等,具體的方法仍是同樣的,這邊就不說了,能夠去看ssm那篇
說說SpringCloud容器和SpringBoot容器的關係唄
首先說一點就是 若是是SpringBoot呢?他是能夠單獨使用的,而SpringCloud是不能單獨使用的,它必須依賴SpringBoot。
在咱們SpringCloud的項目中呢,整個項目的容器分爲三層
- BootStrap Spring 容器:由SpringCloud 監聽器建立,用來初始化 SpringCloud 上下文
- SpringBoot Spring 容器:由SpringBoot建立,也是項目中經常使用的Spring容器。
- 微服務 Spring相關容器:Feign和Ribbon配置類對應的上下文,由配置容器抽象工廠 NamedContextFactory 建立,用於容器隔離。
主要流程
首先 SpringBoot 項目啓動,觸發監聽器,若是引入了SpringCloud 中的BootstrapApplicationListener,則開始初始化 SpringCloud 相關的上下文:Bootstrap ApplicationContext,將其設置爲祖先容器,而後繼續建立其子容器:SpringBoot Application。
說說分佈式系統開發的痛點,業界是怎麼設計的這些解決方案
首先分佈式系統開發,目前主流的架構就是微服務架構,若是說你作微服務架構的話,不管你怎麼去選型,怎麼去設計,首先你總歸要碰到如下的幾個問題
- 這麼多的服務,客戶端如何去訪問,你就比如說咱們幾百個服務,難道前端要在代碼中調用幾百個地址,而況服務地址多了,咱們也很差去管理這些ip和端口,
- 服務與服務之間,如何去通訊,那是否是得處理咱們服務內部之間的調用方式,
- 服務掛了怎麼辦,你不能由於一個服務掛了,致使整個項目出現問題,致使服務雪崩吧
- 服務與服務是如何作到服務的發現與註冊的,你不能說那個服務掛了,我是如何去通知其餘服務的。也就是服務的治理
說說大家公司的SpringCloud的組件吧
- Spring Cloud 核心組件:Eureka 服務發現和註冊中心
- Spring Cloud 核心組件:Feign 服務與服務直接的調用
- Spring Cloud 核心組件:Ribbon 負載均衡
- Spring Cloud 核心組件:Hystrix 熔斷 降級
- Spring Cloud 核心組件:Zuul SpringCloudGateway 服務網關
聊聊Eureka吧
首先什麼是Eureka
首先,eureka在springcloud中充當服務註冊功能,至關於dubbo+zk裏面得zk,可是比zk要簡單得多,zk能夠作得東西太多了,包括分佈式鎖,分佈式隊列都是基於zk裏面得四種節點加watch機制經過長鏈接來實現得,可是eureka不同,eureka是基於HTTprest來實現的,就是把服務的信息放到一個ConcurrentHashMap中,而後服務啓動的時候去讀取這個map,來把全部服務關聯起來,而後服務器之間調用的時候經過信息,進行http調用。eureka包括兩部分,一部分就是服務提供者(對於eureka來講就是客戶端),一部分是服務端,客戶端須要每一個讀取每一個服務的信息,而後註冊到服務端,很明顯了,這個服務端就是接受客戶端提供的自身的一些信息。 目前eureka是ap的 可是呢 zk是cp的,至於分佈式理論下次有空再聊哈。
聊聊eureka中一些重要的概念唄
在Eureka的服務治理中,會涉及到下面一些概念:
- 服務註冊:Eureka Client會經過發送REST請求的方式向Eureka Server註冊本身的服務,提供自身的元數據,好比ip地址、端口、運行情況指標的url、主頁地址等信息。Eureka Server接收到註冊請求後,就會把這些元數據信息存儲在一個雙層的Map中。
- 服務續約:在服務註冊後,Eureka Client會維護一個心跳來持續通知Eureka Server,說明服務一直處於可用狀態,防止被剔除。Eureka Client在默認的狀況下會每隔30秒發送一次心跳來進行服務續約。
- 服務同步:Eureka Server之間會互相進行註冊,構建Eureka Server集羣,不一樣Eureka Server之間會進行服務同步,用來保證服務信息的一致性。
- 獲取服務:服務消費者(Eureka Client)在啓動的時候,會發送一個REST請求給Eureka Server,獲取上面註冊的服務清單,而且緩存在Eureka Client本地,默認緩存30秒。同時,爲了性能考慮,Eureka Server也會維護一份只讀的服務清單緩存,該緩存每隔30秒更新一次。
- 服務調用:服務消費者在獲取到服務清單後,就能夠根據清單中的服務列表信息,查找到其餘服務的地址,從而進行遠程調用。Eureka有Region和Zone的概念,一個Region能夠包含多個Zone,在進行服務調用時,優先訪問處於同一個Zone中的服務提供者。
- 服務下線:當Eureka Client須要關閉或重啓時,就不但願在這個時間段內再有請求進來,因此,就須要提早先發送REST請求給Eureka Server,告訴Eureka Server本身要下線了,Eureka Server在收到請求後,就會把該服務狀態置爲下線(DOWN),並把該下線事件傳播出去。
- 服務剔除:有時候,服務實例可能會由於網絡故障等緣由致使不能提供服務,而此時該實例也沒有發送請求給Eureka Server來進行服務下線,因此,還須要有服務剔除的機制。Eureka Server在啓動的時候會建立一個定時任務,每隔一段時間(默認60秒),從當前服務清單中把超時沒有續約(默認90秒)的服務剔除。
- 自我保護:既然Eureka Server會定時剔除超時沒有續約的服務,那就有可能出現一種場景,網絡一段時間內發生了異常,全部的服務都沒可以進行續約,Eureka Server就把全部的服務都剔除了,這樣顯然不太合理。因此,就有了自我保護機制,當短期內,統計續約失敗的比例,若是達到必定閾值,則會觸發自我保護的機制,在該機制下,Eureka Server不會剔除任何的微服務,等到正常後,再退出自我保護機制。
從這些概念中,就能夠知道大致的流程,Eureka Client向Eureka Server註冊,而且維護心跳來進行續約,若是長時間不續約,就會被剔除。Eureka Server之間進行數據同步來造成集羣,Eureka Client從Eureka Server獲取服務列表,用來進行服務調用,Eureka Client服務重啓前調用Eureka Server的接口進行下線操做。
說說Eureka的一些原理和服務流程
服務提供者
一、啓動後,向註冊中心發起register請求,註冊服務
二、在運行過程當中,定時向註冊中心發送renew心跳,證實「我還活着」。
三、中止服務提供者,向註冊中心發起cancel請求,清空當前服務註冊信息。
服務消費者
一、啓動後,從註冊中心拉取服務註冊信息
二、在運行過程當中,定時更新服務註冊信息。
三、服務消費者發起遠程調用:
註冊中心
一、啓動後,從其餘節點拉取服務註冊信息(節點之間的數據同步)。
二、運行過程當中,定時運行evict任務,剔除沒有按時renew的服務(包括非正常中止和網絡故障的服務)。
三、運行過程當中,接收到的register、renew、cancel請求,都會同步至其餘註冊中心節點。
聊聊Eureka的存儲機制
既然是服務註冊中心,必然要存儲服務的信息,咱們知道ZK是將服務信息保存在樹形節點上。而下面是Eureka的數據存儲結構:
Eureka的數據存儲分了兩層:數據存儲層和緩存層。Eureka Client在拉取服務信息時,先從緩存層獲取(至關於Redis),若是獲取不到,先把數據存儲層的數據加載到緩存中(至關於Mysql),再從緩存中獲取。值得注意的是,數據存儲層的數據結構是服務信息,而緩存中保存的是通過處理加工過的、能夠直接傳輸到Eureka Client的數據結構。
Eureka實現了二級緩存來保存即將要對外傳輸的服務信息,數據結構徹底相同。
一級緩存:ConcurrentHashMap<Key,Value> readOnlyCacheMap,本質上是HashMap,無過時時間,保存服務信息的對外輸出數據結構。
二級緩存:Loading<Key,Value> readWriteCacheMap,本質上是guava的緩存,包含失效機制,保存服務信息的對外輸出數據結構。
Eureka的服務續約機制
服務註冊後,要定時(默認30S,可本身配置)向註冊中心發送續約請求,告訴註冊中心「我還活着」。
註冊中心收到續約請求後:
一、更新服務對象的最近續約時間,即Lease對象的lastUpdateTimestamp;
二、同步服務信息,將此事件同步至其餘的Eureka Server節點。
Eureka服務註銷機制
服務正常中止以前會向註冊中心發送註銷請求,告訴註冊中心「我要下線了」。
註冊中心服務接收到cancel請求後:
一、刪除服務信息,將服務信息從registry中刪除;
二、更新隊列,將此事件添加到更新隊列中,供Eureka Client增量同步服務信息使用。
三、清空二級緩存,即readWriteCacheMap,用於保證數據的一致性。
四、更新閾值,供剔除服務使用。
五、同步服務信息,將此事件同步至其餘的Eureka Server節點。
Eureka自我保護
Eureka自我保護機制是爲了防止誤殺服務而提供的一個機制。Eureka的自我保護機制「謙虛」的認爲若是大量服務都續約失敗,則認爲是本身出問題了(如本身斷網了),也就不剔除了;反之,則是Eureka Client的問題,須要進行剔除。而自我保護閾值是區分Eureka Client仍是Eureka Server出問題的臨界值:若是超出閾值就表示大量服務可用,少許服務不可用,則斷定是Eureka Client出了問題。若是未超出閾值就表示大量服務不可用,則斷定是Eureka Server出了問題。
聊聊feign是啥
Feign是一種聲明式、模板化的HTTP客戶端(僅在Application Client中使用)。聲明式調用是指,就像調用本地方法同樣調用遠程方法,無需感知操做遠程http請求。 Spring Cloud的聲明式調用, 能夠作到使用 HTTP請求遠程服務時能就像調用本地方法同樣的體驗,開發者徹底感知不到這是遠程方法,更感知不到這是個HTTP請求。Feign的應用,讓Spring Cloud微服務調用像Dubbo同樣,Application Client直接經過接口方法調用Application Service,而不須要經過常規的RestTemplate構造請求再解析返回數據。它解決了讓開發者調用遠程接口就跟調用本地方法同樣,無需關注與遠程的交互細節,更無需關注分佈式環境開發。
聊聊Feign的原理唄
咱們來想一想平時咱們使用feign的時候,會是一個怎麼樣的流程
- 添加了 Spring Cloud OpenFeign 的依賴
- 在 SpringBoot 啓動類上添加了註解 @EnableFeignCleints
- 按照 Feign 的規則定義接口 DemoService, 添加@FeignClient 註解
- 在須要使用 Feign 接口 DemoService 的地方, 直接利用@Autowire 進行注入
- 使用接口完成對服務端的調用
那咱們基於這些步驟來分析分析,本文並不會說很是深刻去看每一行的源碼
- SpringBoot 應用啓動時, 由針對 @EnableFeignClient 這一註解的處理邏輯觸發程序掃描 classPath中全部被@FeignClient 註解的類, 這裏以 XiaoLiuLiuService 爲例, 將這些類解析爲 BeanDefinition 註冊到 Spring 容器中
- Sping 容器在爲某些用的 Feign 接口的 Bean 注入 XiaoLiuLiuService 時, Spring 會嘗試從容器中查找 XiaoLiuLiuService 的實現類
- 因爲咱們歷來沒有編寫過 XiaoLiuLiuService 的實現類, 上面步驟獲取到的 XiaoLiuLiuService 的實現類必然是 feign 框架經過擴展 spring 的 Bean 處理邏輯, 爲 XiaoLiuLiuService 建立一個動態接口代理對象, 這裏咱們將其稱爲 XiaoLiuLiuServiceProxy 註冊到spring 容器中。
- Spring 最終在使用到 XiaoLiuLiuService 的 Bean 中注入了 XiaoLiuLiuServiceProxy 這一實例。
- 當業務請求真實發生時, 對於 XiaoLiuLiuService 的調用被統一轉發到了由 Feign 框架實現的 InvocationHandler 中, InvocationHandler 負責將接口中的入參轉換爲 HTTP 的形式, 發到服務端, 最後再解析 HTTP 響應, 將結果轉換爲 Java 對象, 予以返回。
其實就是基於aop代理和麪向切面編程,把那些重複的東西,幫咱們封裝了起來,而後再結合一塊兒其餘的組件如負載均衡Ribbon等。
Hystrix是什麼
在分佈式系統中,每一個服務均可能會調用不少其餘服務,被調用的那些服務就是依賴服務,有的時候某些依賴服務出現故障也是很正常的。
Hystrix 可讓咱們在分佈式系統中對服務間的調用進行控制,加入一些調用延遲或者依賴故障的容錯機制。
Hystrix 經過將依賴服務進行資源隔離,進而阻止某個依賴服務出現故障時在整個系統全部的依賴服務調用中進行蔓延;同時Hystrix 還提供故障時的 fallback 降級機制。
總而言之,Hystrix 經過這些方法幫助咱們提高分佈式系統的可用性和穩定性。
hystrix實現原理
hystrix語義爲「豪豬」,具備自我保護的能力。hystrix的出現即爲解決雪崩效應,它經過四個方面的機制來解決這個問題
- 隔離(線程池隔離和信號量隔離):限制調用分佈式服務的資源使用,某一個調用的服務出現問題不會影響其餘服務調用。
- 優雅的降級機制:超時降級、資源不足時(線程或信號量)降級,降級後能夠配合降級接口返回託底數據。
- 融斷:當失敗率達到閥值自動觸發降級(如因網絡故障/超時形成的失敗率高),熔斷器觸發的快速失敗會進行快速恢復。
- 緩存:提供了請求緩存、請求合併實現。
- 支持實時監控、報警、控制(修改配置)
聊聊hystrix的隔離機制
- 線程池隔離模式:使用一個線程池來存儲當前的請求,線程池對請求做處理,設置任務返回處理超時時間,堆積的請求堆積入線程池隊列。這種方式須要爲每一個依賴的服務申請線程池,有必定的資源消耗,好處是能夠應對突發流量(流量洪峯來臨時,處理不完可將數據存儲到線程池隊裏慢慢處理)
- 信號量隔離模式:使用一個原子計數器(或信號量)來記錄當前有多少個線程在運行,請求來先判斷計數器的數值,若超過設置的最大線程個數則丟棄改類型的新請求,若不超過則執行計數操做請求來計數器+1,請求返回計數器-1。這種方式是嚴格的控制線程且當即返回模式,沒法應對突發流量(流量洪峯來臨時,處理的線程超過數量,其餘的請求會直接返回,不繼續去請求依賴的服務)
聊聊hystrix的融斷機制 和降級
熔斷器模式定義了熔斷器開關相互轉換的邏輯。
- 服務的健康情況 = 請求失敗數 / 請求總數。熔斷器開關由關閉到打開的狀態轉換是經過當前服務健康情況和設定閾值比較決定的。
- 當熔斷器開關關閉時,請求被容許經過熔斷器。 若是當前健康情況高於設定閾值,開關繼續保持關閉。若是當前健康情況低於設定閾值,開關則切換爲打開狀態。當熔斷器開關打開時,請求被禁止經過。當熔斷器開關處於打開狀態,通過一段時間後,熔斷器會自動進入半開狀態,這時熔斷器只容許一個請求經過。當該請求調用成功時,熔斷器恢復到關閉狀態。若該請求失敗,熔斷器繼續保持打開狀態,接下來的請求被禁止經過。
- 熔斷器的開關能保證服務調用者在調用異常服務時,快速返回結果,避免大量的同步等待,而且熔斷器能在一段時間後繼續偵測請求執行結果,提供恢復服務調用的可能。
降級須要對下層依賴的業務分級,把產生故障的丟了,換一個輕量級的方案,是一種退而求其次的方法,說白了就是咱們代碼中常常用到的fallback,好比說直接返回一個靜態的常量之類的。
什麼是網關
網關是整個微服務API請求的入口,負責攔截全部請求,分發到服務上去。能夠實現日誌攔截、權限控制、解決跨域問題、限流、熔斷、負載均衡,隱藏服務端的ip,黑名單與白名單攔截、受權等,經常使用的網關有zuul(netflix的,可是已經停更了)和spring cloud gateway (springcloudalibaba)。這裏主要講springcloud gateway,springcloud gateway是一個全新的項目,其基於spring5.0 以及springboot2.0和項目Reactor等技術開發的網關,其主要的目的是爲微服務架構提供一種簡單有效的API路由管理方式.
綜上:通常狀況下,網關通常都會提供請求轉發、安全認證(身份/權限認證)、流量控制、負載均衡、容災、日誌、監控這些功能。
聊聊Spring Cloud Gateway的大體流程
- 路由的配置轉換爲routeDefinition
- 獲取請求對應的路由規則, 將RouteDefinition轉換爲Route
- 執行Predicate判斷是否符合路由, 以及執行相關的過濾(全局過濾器以及路由過濾器)
- 負載均衡過濾器負責將請求中的serviceId轉換爲具體的服務實例Ip
其實網關其實還有不少說的,由於網關企業級的網關分類比較多,好比咱們的對外網關 對內網關,對合做夥伴的網關等
網關的設計方案
- 基於Nginx+Lua+ OpenResty的方案,能夠看到Kong,orange都是基於這個方案
- 基於Netty、非阻塞IO模型。 經過網上搜索能夠看到國內的宜人貸等一些公司是基於這種方案,是一種成熟的方案。
- 基於Node.js的方案。 這種方案是應用了Node.js天生的非阻塞的特性。
- 基於java Servlet的方案。 zuul基於的就是這種方案,這種方案的效率不高,這也是zuul老是被詬病的緣由。
最後問一個問題,mysql分庫分表下的數據遷移問題
問題場景:就是好比說咱們一開始設計架構的時候,咱們並不知道這個項目能火,可是忽然老闆拿到了融資,而後數據量起來,原來的架構抗不住了,這個時候須要分庫分表了,你怎麼去遷移,怎麼保證遷移以後的數據一致性
停機部署法
大體思路就是,掛一個公告,半夜停機升級,而後半夜把服務停了,跑數據遷移程序,進行數據遷移。 步驟以下:
- 出一個公告,好比「今晚00:00~6:00進行停機維護,暫停服務」
- 寫一個遷移程序,讀db-old數據庫,經過中間件寫入新庫
- 而後測試一下數據的一致性
你們不要以爲這種方法low,我其實一直以爲這種方法可靠性很強。並且我相信大部分公司必定不是什麼很牛逼的互聯網公司,若是大家的產品凌晨1點的用戶活躍數還有超過1000的,大家握個爪!畢竟不是全部人都在什麼電商公司的,大部分產品半夜都沒啥流量。因此此方案,並不是沒有可取之處。
可是此方案有一個缺點,累!不止身體累,心也累!你想一想看,原本定六點結束,你五點把數據庫遷移好,可是不知怎麼滴,程序切新庫就是有點問題。因而,眼瞅着天就要亮了,趕忙把數據庫切回老庫。第二個晚上繼續這麼幹,簡直是身心俱疲。 ps:這裏教你們一些技巧啊,若是你真的沒作過度庫分表,又想吹一波,漲一下工資,建議答這個方案。由於這個方案比較low,low到沒什麼東西能夠深挖的,因此答這個方案,比較靠譜。
雙寫部署法
- 首先咱們用canal去監聽咱們須要分庫分表的那個表,就是上線以後的那些事務操做,而後把它放到隊列裏面,存起來,先不消費。
- 啓動一個程序把舊數據同步到分庫分表的數據庫,這裏有一個問題怎麼區分新舊數據,就是當這個項目啓動的時候,算出最大的id,這個以前的就是老數據了,或者是按更新時間排序,再這個時間以前的就是老數據,以後的就是新數據了。
- 最後把遷移數據下線,再去消費隊列,完成數據的遷移
- 測試驗證數據是否正常
結束
下面咱們來看看分佈式的理論和Zk,對於分佈式系統開發仍是須要明白的。
平常求贊
好了各位,以上就是這篇文章的所有內容了,能看到這裏的人呀,都是
真粉。
創做不易,各位的支持和承認,就是我創做的最大動力,咱們下篇文章見
微信 搜 "六脈神劍的程序人生" 回覆888 有我找的許多的資料送給你們