分布式系統如果保證接口的冪等性?
- 數據設置狀態值
- 數據庫設置唯一性
- 每個數據請求有唯一性標識
分布式session如何處理?
- tomcat+redis,TomcatRedisSessionManager,將所有部署的tomcat都將session存儲到redis即可。使用方法不變,是Tomcat封裝的類將session存儲到了redis,依賴web容器
- spring session +redis:spring 將session存儲到redis
分庫分表
- 為什么要分庫分表?表數據量達到上千萬級別,數據庫磁盤消耗高,QPS響應慢,需要通過分庫分表來優化
- 分庫分表中間件?中間件有client類型,proxy類型
什么是垂直分和水平分?
如何平滑的執行分庫分表?
- 啟動多個線程讀取原始數據到數據中間件中
- 雙寫遷移方案:
-
分庫分表之后全局唯一ID如何生成(主鍵自增ID)?
- 全局表:生成主鍵ID的全局數據庫A,每次都去數據庫A里面得到主鍵ID,然后再去其他數據庫insert 數據。瓶頸:單庫,適用於 並發量小,數據大的情況,每秒最高並發最大為幾百的合適。
- uuid :本地生成,不基於數據庫,存儲空間大,字段太長,做為主鍵性能差
- 利用redis的incr原子性操作自增,可以一次增長incrby order 100,一次申請100個自增ID,然后自己在內存通過自增實現,減少占用內存請求資源
- MySQL多實例主鍵自增 :優點:解決了單點問題,缺點:確定了步長 無法再次擴容
5.雪花算法(snowflake) :整體上按照時間自增排序,並且整個分布式系統內不會產生ID碰撞(由數據中心ID和機器ID作區分),並且效率較高,經測試,SnowFlake每秒能夠產生26萬ID左右。缺點:強依賴機器時鍾,如果機器上時鍾回撥,會導致發號重復或者服務會處於不可用狀態。
②生成id的結果是一個64bit大小的整數,為一個Long型(轉換成字符串后長度最多19)
③分布式系統內不會產生ID碰撞(由datacenter和workId作區分)並且效率較高

-
1bit,不用,因為二進制中最高位是符號位,1表示負數,0表示正數。生成的id一般都是用整數,所以最高位固定為0。
-
41bit-時間戳,用來記錄時間戳,毫秒級。
- 41位可以表示個數字,
- 如果只用來表示正整數(計算機中正數包含0),可以表示的數值范圍是:0 至,減1是因為可表示的數值范圍是從0開始算的,而不是1。
- 也就是說41位可以表示個毫秒的值,轉化成單位年則是
年
-
10bit-工作機器id,用來記錄工作機器id。
- 可以部署在個節點,包括5位datacenterId和5位workerId
- 5位(bit)可以表示的最大正整數是,即可以用0、1、2、3、....31這32個數字,來表示不同的datecenterId或workerId
-
12bit-序列號,序列號,用來記錄同毫秒內產生的不同id。
- 12位(bit)可以表示的最大正整數是,即可以用0、1、2、3、....4094這4095個數字,來表示同一機器同一時間截(毫秒)內產生的4095個ID序號。
SnowFlake可以保證
所有生成的id按時間趨勢遞增
整個分布式系統內不會產生重復id(因為有datacenterId和workerId來做區分)
什么是讀寫分離?為什么要有讀寫分離?
數據庫一般 請求 2000/s,大於該請求就會出現磁盤高,性能瓶頸。大部分是讀大於寫,針對這個問題可以通過一個 主庫掛多個從庫,從庫讀數據,支持更高的並發
如何實現讀寫分離?
主庫將變更寫到binlog日志,然后從庫連接到主庫之后,從庫有一個IO線程,將主庫的binlog日志拷貝到自己的relay log中,從庫的SQL線程從relay log中讀取binlog,然后執行binlog日志中的內容,在自己本地在執行一遍SQL,這樣就完成了從庫和主庫的數據是一樣的。
Mysql主從復制原理?
1. 主庫對所有DDL和DML產生的日志寫進binlog;
2. 主庫生成一個 log dump 線程,用來給從庫I/O線程讀取binlog;
3. 從庫的I/O Thread去請求主庫的binlog,並將得到的binlog日志寫到relay log文件中;
4. 從庫的SQL Thread會讀取relay log文件中的日志解析成具體操作,將主庫的DDL和DML操作事件重放。
關於DDL和DML
SQL語言共分為四大類:查詢語言DQL,控制語言DCL,操縱語言DML,定義語言DDL。
DQL:可以簡單理解為SELECT語句;
DCL:GRANT、ROLLBACK和COMMIT一類語句;
DML:可以理解為CREATE一類的語句;
DDL:INSERT、UPDATE和DELETE語句都是;
Mysql主從同步的延時問題?
現象:從庫同步主庫數據的過程是串行化的,主庫是並行的操作,在從庫上會串行(順序)執行。由於從庫從主庫拷貝日志然后串行執行SQL的特點,在高並發場景下,從庫的數據一定會比主庫慢一些,有延時,寫入的主庫數據可能是讀不到的,要過幾十毫秒,甚至幾百毫秒才能讀取到。
1.MySQL的主從復制都是單線程的操作,主庫對所有DDL和DML產生的日志寫進binlog,由於binlog是順序寫,所以效率很高。Slave的SQL Thread線程將主庫的DDL和DML操作事件在slave中重放。DML和DDL的IO操作是隨即的,不是順序的,成本高很多。
2.由於SQL Thread也是單線程的,當主庫的並發較高時,產生的DML數量超過slave的SQL Thread所能處理的速度,或者當slave中有大型query語句產生了鎖等待那么延時就產生了。
常見原因:Master負載過高、Slave負載過高、網絡延遲、機器性能太低、MySQL配置不合理。
主從延遲排查方法?
通過監控 show slave status 命令輸出的Seconds_Behind_Master參數的值來判斷:
NULL:表示io_thread或是sql_thread有任何一個發生故障;
0:該值為零,表示主從復制良好;
正值:表示主從已經出現延時,數字越大表示從庫延遲越嚴重。
解決從庫復制延遲的問題?
1. 優化網絡
2. 升級Slave硬件配置
3. Slave調整參數,關閉binlog,修改innodb_flush_log_at_trx_commit參數值
4. 升級MySQL版本到5.7,使用並行復制:從庫開啟多個線程,並行讀取relay log中不同庫的日志,然后並行重放不同庫的日志,這就是庫級別(基於庫的)的並行
主庫突然宕機日志沒有寫到binlog(數據丟失問題)?
主庫突然宕機日志沒有寫到binlog,那么主庫就丟失了這條數據如何解決?
半同步復制(semi-sync復制):主庫寫入binlog日志之后,強制立即將數據同步到從庫,從庫將日志寫入本地的relay log之后,返回一個ack給主庫,主庫收到從庫ack請求(需要等待至少一個從庫接收到並寫到relay log中才返回結果給客戶端),才認為是寫操作完成了。 半同步復制提高了數據的安全性,同時它也造成了一個TCP/IP往返耗時的延遲。(所以寫庫失敗,需要重試解決丟失數據問題)
relay-log(中繼日志)
存儲所有主庫TP過來的binlog事件主庫binlog,記錄主庫發生過的修改事件。