HTTP 1.0主要有以下幾點變化:
請求和相應可以由于多行首部字段構成
響應對象前面添加了一個響應狀態行
響應對象不局限于超文本
服務器與客戶端之間的連接在每次請求之后都會關閉
實現了Expires等傳輸內容的緩存控制
內容編碼Accept-Encoding、字符集Accept-Charset等協商內容的支持
這時候開始有了請求及返回首部的概念,開始傳輸不限于文本(其他二進制內容)
HTTP 1.1加入了很多重要的性能優化:持久連接、分塊編碼傳輸、字節范圍請求、增強的緩存機制、傳輸編碼及請求管道。
http://imweb.io/topic/554c5879718ba1240cc1dd8a
TCP 三次握手和四次揮手的流程,為什么斷開連接要 4 次,如果握手只有兩次,會出現什么。
第一次握手(SYN=1, seq=x):
客戶端發送一個 TCP 的 SYN 標志位置1的包,指明客戶端打算連接的服務器的端口,以及初始序號 X,保存在包頭的序列號(Sequence Number)字段里。
發送完畢后,客戶端進入SYN_SEND狀態。
第二次握手(SYN=1, ACK=1, seq=y, ACKnum=x+1):
服務器發回確認包(ACK)應答。即 SYN 標志位和 ACK 標志位均為1。服務器端選擇自己 ISN 序列號,放到 Seq 域里,同時將確認序號(Acknowledgement Number)設置為客戶的 ISN 加1,即X+1。
發送完畢后,服務器端進入SYN_RCVD狀態。
第三次握手(ACK=1,ACKnum=y+1)
客戶端再次發送確認包(ACK),SYN 標志位為0,ACK 標志位為1,并且把服務器發來 ACK 的序號字段+1,放在確定字段中發送給對方,并且在數據段放寫ISN的+1
發送完畢后,客戶端進入ESTABLISHED狀態,當服務器端接收到這個包時,也進入ESTABLISHED狀態,TCP 握手結束。
第一次揮手(FIN=1,seq=x)
假設客戶端想要關閉連接,客戶端發送一個 FIN 標志位置為1的包,表示自己已經沒有數據可以發送了,但是仍然可以接受數據。
發送完畢后,客戶端進入 FIN_WAIT_1 狀態。
第二次揮手(ACK=1,ACKnum=x+1)
服務器端確認客戶端的 FIN 包,發送一個確認包,表明自己接受到了客戶端關閉連接的請求,但還沒有準備好關閉連接。
發送完畢后,服務器端進入 CLOSE_WAIT 狀態,客戶端接收到這個確認包之后,進入 FIN_WAIT_2 狀態,等待服務器端關閉連接。
第三次揮手(FIN=1,seq=y)
服務器端準備好關閉連接時,向客戶端發送結束連接請求,FIN 置為1。
發送完畢后,服務器端進入 LAST_ACK 狀態,等待來自客戶端的最后一個ACK。
第四次揮手(ACK=1,ACKnum=y+1)
客戶端接收到來自服務器端的關閉請求,發送一個確認包,并進入 TIME_WAIT狀態,等待可能出現的要求重傳的 ACK 包。
服務器端接收到這個確認包之后,關閉連接,進入 CLOSED 狀態。
客戶端等待了某個固定時間(兩個最大段生命周期,2MSL,2 Maximum Segment Lifetime)之后,沒有收到服務器端的 ACK ,認為服務器端已經正常關閉連接,于是自己也關閉連接,進入 CLOSED 狀態。
兩次后會重傳直到超時。如果多了會有大量半鏈接阻塞隊列。
https://segmentfault.com/a/1190000006885287
https://hit-alibaba.github.io/interview/basic/network/TCP.html
TIME_WAIT狀態就是用來重發可能丟失的ACK報文。
TIME_WAIT 表示主動關閉,CLOSE_WAIT 表示被動關閉。
說說你知道的幾種 HTTP 響應碼,比如 200, 302, 404。
1xx:信息,請求收到,繼續處理
2xx:成功,行為被成功地接受、理解和采納
3xx:重定向,為了完成請求,必須進一步執行的動作
4xx:客戶端錯誤,請求包含語法錯誤或者請求無法實現
5xx:服務器錯誤,服務器不能實現一種明顯無效的請求
200 ok 一切正常
302 Moved Temporatily 文件臨時移出
404 not found
https://my.oschina.net/gavinjin/blog/42856
Dns解析–>端口分析–>tcp請求–>服務器處理請求–>服務器響應–>瀏覽器解析—>鏈接關閉
使用序號,對收到的TCP報文段進行排序以及檢測重復的數據;使用校驗和來檢測報文段的錯誤;使用確認和計時器來檢測和糾正丟包或延時。//TCP頭部,總長度20字節
typedef struct _tcp_hdr
{
unsigned short src_port; //源端口號
unsigned short dst_port; //目的端口號
unsigned int seq_no; //序列號
unsigned int ack_no; //確認號
#if LITTLE_ENDIAN
unsigned char reserved_1:4; //保留6位中的4位首部長度
unsigned char thl:4; //tcp頭部長度
unsigned char flag:6; //6位標志
unsigned char reseverd_2:2; //保留6位中的2位
#else
unsigned char thl:4; //tcp頭部長度
unsigned char reserved_1:4; //保留6位中的4位首部長度
unsigned char reseverd_2:2; //保留6位中的2位
unsigned char flag:6; //6位標志
#endif
unsigned short wnd_size; //16位窗口大小
unsigned short chk_sum; //16位TCP檢驗和
unsigned short urgt_p; //16為緊急指針
}tcp_hdr;
https://zh.bywiki.com/zh-hans/%E4%BC%A0%E8%BE%93%E6%8E%A7%E5%88%B6%E5%8D%8F%E8%AE%AE
無法被瀏覽器緩存的請求:
HTTP信息頭中包含Cache-Control:no-cache,pragma:no-cache,或Cache-Control:max-age=0等告訴瀏覽器不用緩存的請求
需要根據Cookie,認證信息等決定輸入內容的動態請求是不能被緩存的
經過HTTPS安全加密的請求(有人也經過測試發現,ie其實在頭部加入Cache-Control:max-age信息,firefox在頭部加入Cache-Control:Public之后,能夠對HTTPS的資源進行緩存,參考《HTTPS的七個誤解》)
POST請求無法被緩存
HTTP響應頭中不包含Last-Modified/Etag,也不包含Cache-Control/Expires的請求無法被緩存
http://www.alloyteam.com/2012/03/web-cache-2-browser-cache/
簡述 Http 請求 get 和 post 的區別以及數據包格式。
http://www.w3school.com.cn/tags/html_ref_httpmethods.asp
http://www.360doc.com/content/12/0612/14/8093902_217673378.shtml
參考上面
加密方式是tls/ssl,底層是通過對稱算法,非對稱,hash算法實現
客戶端發起HTTPS請求 –》2. 服務端的配置 –》
3. 傳送證書 —》4. 客戶端解析證書 5. 傳送加密信息 6. 服務段解密信息 7. 傳輸加密后的信息 8. 客戶端解密信息
http://www.cnblogs.com/zhuqil/archive/2012/07/23/2604572.html
常見的緩存策略有哪些,你們項目中用到了什么緩存系統,如何設計的。
Cdn緩存,redis緩存,ehcache緩存等
Cdn 圖片資源 js等, redis一主一從 echcache緩存數據
final int cacheSize = 100;
Map
Redis生成,mongodb的objectId,zk生成
http://www.cnblogs.com/haoxinyue/p/5208136.html
分流 – 限流–異步–公平性(只能參加一次)–用戶體驗(第幾位,多少分鐘,一搶完)
容錯處理
Redis 隊列 mysql
30分鐘關閉 可以借助redis的發布訂閱機制 在失效時進行后續操作,其他mq也可以
http://www.infoq.com/cn/articles/yhd-11-11-queuing-system-design
如何使用 redis 和 zookeeper 實現分布式鎖?有什么區別優缺點,分別適用什么場景。
首先分布式鎖實現常見的有數據庫鎖(表記錄),緩存鎖,基于zk(臨時有序節點可以實現的)的三種
Redis適用于對性能要求特別高的場景。redis可以每秒執行10w次,內網延遲不超過1ms
缺點是數據存放于內存,宕機后鎖丟失。
鎖無法釋放?使用Zookeeper可以有效的解決鎖無法釋放的問題,因為在創建鎖的時候,客戶端會在ZK中創建一個臨時節點,一旦客戶端獲取到鎖之后突然掛掉(Session連接斷開),那么這個臨時節點就會自動刪除掉。其他客戶端就可以再次獲得鎖。
非阻塞鎖?使用Zookeeper可以實現阻塞的鎖,客戶端可以通過在ZK中創建順序節點,并且在節點上綁定監聽器,一旦節點有變化,Zookeeper會通知客戶端,客戶端可以檢查自己創建的節點是不是當前所有節點中序號最小的,如果是,那么自己就獲取到鎖,便可以執行業務邏輯了。
不可重入?使用Zookeeper也可以有效的解決不可重入的問題,客戶端在創建節點的時候,把當前客戶端的主機信息和線程信息直接寫入到節點中,下次想要獲取鎖的時候和當前最小的節點中的數據比對一下就可以了。如果和自己的信息一樣,那么自己直接獲取到鎖,如果不一樣就再創建一個臨時的順序節點,參與排隊。
單點問題?使用Zookeeper可以有效的解決單點問題,ZK是集群部署的,只要集群中有半數以上的機器存活,就可以對外提供服務。
http://www.hollischuang.com/archives/1716
可以使用filter過濾處理
Two Phase commit協議
優點是可以管理多機事務,擁有無線擴展性 確定是易用性難,承擔延時風險
JTA,atomiks等
https://yq.aliyun.com/webinar/join/185?spm=5176.8067841.0.0.RL4GDa
一致性hash是一種分布式hash實現算法。滿足平衡性 單調性 分散性 和負載。
http://blog.csdn.net/cywosp/article/details/23397179/
REST 指的是一組架構約束條件和原則。滿足這些約束條件和原則的應用程序或設計就是 RESTful。
服務器內核調優(tcp,文件數),客戶端調優,框架選擇(netty)
緩存雪崩可能是因為數據未加載到緩存中,或者緩存同一時間大面積的失效,從而導致所有請求都去查數據庫,導致數據庫CPU和內存負載過高,甚至宕機。
解決思路:
1,采用加鎖計數,或者使用合理的隊列數量來避免緩存失效時對數據庫造成太大的壓力。這種辦法雖然能緩解數據庫的壓力,但是同時又降低了系統的吞吐量。
2,分析用戶行為,盡量讓失效時間點均勻分布。避免緩存雪崩的出現。
3,如果是因為某臺緩存服務器宕機,可以考慮做主備,比如:redis主備,但是雙緩存涉及到更新事務的問題,update可能讀到臟數據,需要好好解決。
http://www.cnblogs.com/jinjiangongzuoshi/archive/2016/03/03/5240280.html
MESI是四種緩存段狀態的首字母縮寫,任何多核系統中的緩存段都處于這四種狀態之一。我將以相反的順序逐個講解,因為這個順序更合理:
失效(Invalid)緩存段,要么已經不在緩存中,要么它的內容已經過時。為了達到緩存的目的,這種狀態的段將會被忽略。一旦緩存段被標記為失效,那效果就等同于它從來沒被加載到緩存中。
共享(Shared)緩存段,它是和主內存內容保持一致的一份拷貝,在這種狀態下的緩存段只能被讀取,不能被寫入。多組緩存可以同時擁有針對同一內存地址的共享緩存段,這就是名稱的由來。
獨占(Exclusive)緩存段,和S狀態一樣,也是和主內存內容保持一致的一份拷貝。區別在于,如果一個處理器持有了某個E狀態的緩存段,那其他處理器就不能同時持有它,所以叫“獨占”。這意味著,如果其他處理器原本也持有同一緩存段,那么它會馬上變成“失效”狀態。
已修改(Modified)緩存段,屬于臟段,它們已經被所屬的處理器修改了。如果一個段處于已修改狀態,那么它在其他處理器緩存中的拷貝馬上會變成失效狀態,這個規律和E狀態一樣。此外,已修改緩存段如果被丟棄或標記為失效,那么先要把它的內容回寫到內存中——這和回寫模式下常規的臟段處理方式一樣。
哈希(Hash)算法,即散列函數。 它是一種單向密碼體制,即它是一個從明文到密文的不可逆的映射,只有加密過程,沒有解密過程。 同時,哈希函數可以將任意長度的輸入經過變化以后得到固定長度的輸出
MD4 MD5 SHA
http://blog.jobbole.com/106733/
Paxos算法是萊斯利·蘭伯特(Leslie Lamport,就是 LaTeX 中的”La”,此人現在在微軟研究院)于1990年提出的一種基于消息傳遞的一致性算法。
http://baike.baidu.com/item/Paxos%20%E7%AE%97%E6%B3%95
ZAB 是 Zookeeper 原子廣播協議的簡稱
整個ZAB協議主要包括消息廣播和崩潰恢復兩個過程,進一步可以分為三個階段,分別是:
發現 Discovery
同步 Synchronization
廣播 Broadcast
組成ZAB協議的每一個分布式進程,都會循環執行這三個階段,將這樣一個循環稱為一個主進程周期。
https://zzzvvvxxxd.github.io/2016/08/09/ZAB/
一個在線文檔系統,文檔可以被編輯,如何防止多人同時對同一份文檔進行編輯更新。
點擊編輯的時候,利用redis進行加鎖setNX完了之后 expire 一下
也可以用版本號進行控制
逐級排查(網絡,磁盤,內存,cpu),數據庫,日志,中間件等也可通過監控工具排查。
單例, 代理,模板,策略,命令
http://www.lxweimin.com/p/bdf65e4afbb0
Dubbo 的原理,數據怎么流轉的,怎么實現集群,負載均衡,服務注冊和發現。重試轉發,快速失敗的策略是怎樣的。
Dubbo[]是一個分布式服務框架,致力于提供高性能和透明化的RPC遠程服務調用方案,以及SOA服務治理方案。
在集群負載均衡時,Dubbo提供了多種均衡策略,缺省為random隨機調用。
Random LoadBalance:隨機,按權重比率設置隨機概率。
RoundRobin LoadBalance:輪循,按公約后的權重比率設置輪循比率。
LeastActive LoadBalance:最少活躍調用數,相同活躍數的隨機,活躍數指調用前后計數差。使慢的提供者收到更少請求,因為越慢的提供者的調用前后計數差會越大。
ConsistentHash LoadBalance:一致性Hash,相同參數的請求總是發到同一提供者。當某一臺提供者掛時,原本發往該提供者的請求,基于虛擬節點,平攤到其它提供者,不會引起劇烈變動。
快速失敗,只發起一次調用,失敗立即報錯。
https://my.oschina.net/u/1378920/blog/693374
1)服務消費方(client)調用以本地調用方式調用服務;
2)client stub接收到調用后負責將方法、參數等組裝成能夠進行網絡傳輸的消息體;
3)client stub找到服務地址,并將消息發送到服務端;
4)server stub收到消息后進行解碼;
5)server stub根據解碼結果調用本地的服務;
6)本地服務執行并將結果返回給server stub;
7)server stub將返回結果打包成消息并發送至消費方;
8)client stub接收到消息,并進行解碼;
9)服務消費方得到最終結果。
異步模式使用與服務器多核,并發嚴重的場景
可提高服務吞吐量大,不容易受到沖擊,可以采用并發策略,提高響應時間
緩存數據過期后的更新如何設計。
失效:應用程序先從cache取數據,沒有得到,則從數據庫中取數據,成功后,放到緩存中。
命中:應用程序從cache中取數據,取到后返回。
更新:先把數據存到數據庫中,成功后,再讓緩存失效。
編程中自己都怎么考慮一些設計原則的,比如開閉原則,以及在工作中的應用。
開閉原則(Open Close Principle)
一個軟件實體如類、模塊和函數應該對擴展開放,對修改關閉。
里氏代換原則(Liskov Substitution Principle)
子類型必須能夠替換掉它們的父類型。
依賴倒轉原則(Dependence Inversion Principle)
高層模塊不應該依賴低層模塊,二者都應該依賴其抽象;抽象不應該依賴細節;細節應該依賴抽象。即針對接口編程,不要針對實現編程
接口隔離原則(Interface Segregation Principle)
建立單一接口,不要建立龐大臃腫的接口,盡量細化接口,接口中的方法盡量少
組合/聚合復用原則
說要盡量的使用合成和聚合,而不是繼承關系達到復用的目的
迪米特法則(Law Of Demeter)
迪米特法則其根本思想,是強調了類之間的松耦合,類之間的耦合越弱,越有利于復用,一個處在弱耦合的類被修改,不會對有關系的類造成影響,也就是說,信息的隱藏促進了軟件的復用。
單一職責原則(Single Responsibility Principle)
一個類只負責一項職責,應該僅有一個引起它變化的原因
http://www.banzg.com/archives/225.html
設計一個社交網站中的“私信”功能,要求高并發、可擴展等等。 畫一下架構圖。
MVC 模式,即常見的 MVC 框架。
SSM SSH SSI等
請思考一個方案,設計一個可以控制緩存總體大小的自動適應的本地緩存。
請思考一個方案,實現分布式環境下的 countDownLatch。
可以通過token值進行防止重復提交,存放到redis中,在表單初始化的時候隱藏在表單中,添加的時候在移除。判斷這個狀態即可防止重復提交。
如何看待緩存的使用(本地緩存,集中式緩存),簡述本地緩存和集中式緩存和優缺點。本地緩存在并發使用時的注意事項。
有 1 億個數字,其中有 2 個是重復的,快速找到它,時間和空間要最優。
給一個不知道長度的(可能很大)輸入字符串,設計一種方案,將重復的字符排重。
有 3n+1 個數字,其中 3n 個中是重復的,只有 1 個是不重復的,怎么找出來。
常用的排序算法,快排,歸并、冒泡。 快排的最優時間復雜度,最差復雜度。冒泡排序的優化方案。
數據庫隔離級別有哪些,各自的含義是什么,MYSQL 默認的隔離級別是是什么。
·未提交讀(Read Uncommitted):允許臟讀,也就是可能讀取到其他會話中未提交事務修改的數據
·提交讀(Read Committed):只能讀取到已經提交的數據。Oracle等多數數據庫默認都是該級別 (不重復讀)
·可重復讀(Repeated Read):可重復讀。在同一個事務內的查詢都是事務開始時刻一致的,InnoDB默認級別。在SQL標準中,該隔離級別消除了不可重復讀,但是還存在幻象讀
·串行讀(Serializable):完全串行化的讀,每次讀都需要獲得表級共享鎖,讀寫相互都會阻塞
MYSQL默認是RepeatedRead級別
MyISAM: 擁有較高的插入,查詢速度,但不支持事務
InnoDB :5.5版本后Mysql的默認數據庫,事務型數據庫的首選引擎,支持ACID事務,支持行級鎖定
BDB: 源自Berkeley DB,事務型數據庫的另一種選擇,支持COMMIT和ROLLBACK等其他事務特性
Memory :所有數據置于內存的存儲引擎,擁有極高的插入,更新和查詢效率。但是會占用和數據量成正比的內存空間。并且其內容會在Mysql重新啟動時丟失
Merge :將一定數量的MyISAM表聯合而成一個整體,在超大規模數據存儲時很有用
Archive :非常適合存儲大量的獨立的,作為歷史記錄的數據。因為它們不經常被讀取。Archive擁有高效的插入速度,但其對查詢的支持相對較差
Federated: 將不同的Mysql服務器聯合起來,邏輯上組成一個完整的數據庫。非常適合分布式應用
Cluster/NDB :高冗余的存儲引擎,用多臺數據機器聯合提供服務以提高整體性能和安全性。適合數據量大,安全和性能要求高的應用
CSV: 邏輯上由逗號分割數據的存儲引擎。它會在數據庫子目錄里為每個數據表創建一個.CSV文件。這是一種普通文本文件,每個數據行占用一個文本行。CSV存儲引擎不支持索引。
BlackHole :黑洞引擎,寫入的任何數據都會消失,一般用于記錄binlog做復制的中繼
另外,Mysql的存儲引擎接口定義良好。有興趣的開發者通過閱讀文檔編寫自己的存儲引擎。
http://baike.baidu.com/item/%E5%AD%98%E5%82%A8%E5%BC%95%E6%93%8E
使用悲觀鎖 悲觀鎖本質是當前只有一個線程執行操作,結束了喚醒其他線程進行處理。
也可以緩存隊列中鎖定主鍵。
樂觀鎖和悲觀鎖是什么,INNODB 的行級鎖有哪 2 種,解釋其含義。
樂觀鎖是設定每次修改都不會沖突,只在提交的時候去檢查,悲觀鎖設定每次修改都會沖突,持有排他鎖。
行級鎖分為共享鎖和排他鎖兩種 共享鎖又稱讀鎖 排他鎖又稱寫鎖
http://www.lxweimin.com/p/f40ec03fd0e8
SQL 優化的一般步驟是什么,怎么看執行計劃,如何理解其中各個字段的含義。
查看慢日志(show [session|gobal] status ),定位慢查詢,查看慢查詢執行計劃 根據執行計劃確認優化方案
Explain sql
select_type:表示select類型。常見的取值有SIMPLE(簡單表,即不使用連接或者子查詢)、PRIMARY(主查詢,即外層的查詢)、UNION(union中的第二個或者后面的查詢語句)、SUBQUERY(子查詢中的第一個SELECT)等。
talbe:輸出結果集的表。
type:表的連接類型。性能由高到底:system(表中僅有一行)、const(表中最多有一個匹配行)、eq_ref、ref、ref_null、index_merge、unique_subquery、index_subquery、range、idnex等
possible_keys:查詢時,可能使用的索引
key:實際使用的索引
key_len:索引字段的長度
rows:掃描行的數量
Extra:執行情況的說明和描述
http://blog.csdn.net/hsd2012/article/details/51106285
數據庫會死鎖嗎,舉一個死鎖的例子,mysql 怎么解決死鎖。
產生死鎖的原因主要是:
(1)系統資源不足。
(2) 進程運行推進的順序不合適。
(3)資源分配不當等。
如果系統資源充足,進程的資源請求都能夠得到滿足,死鎖出現的可能性就很低,否則就會因爭奪有限的資源而陷入死鎖。其次,進程運行推進順序與速度不同,也可能產生死鎖。
產生死鎖的四個必要條件:
(1) 互斥條件:一個資源每次只能被一個進程使用。
(2) 請求與保持條件:一個進程因請求資源而阻塞時,對已獲得的資源保持不放。
(3) 不剝奪條件:進程已獲得的資源,在末使用完之前,不能強行剝奪。
(4) 循環等待條件:若干進程之間形成一種頭尾相接的循環等待資源關系。
這四個條件是死鎖的必要條件,只要系統發生死鎖,這些條件必然成立,而只要上述條件之一不滿足,就不會發生死鎖。
這里提供兩個解決數據庫死鎖的方法:
1)重啟數據庫(誰用誰知道)
2)殺掉搶資源的進程:
先查哪些進程在搶資源:SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;
殺掉它們:Kill trx_mysql_thread_id;
MYsql 的索引原理,索引的類型有哪些,如何創建合理的索引,索引如何優化。
索引是通過復雜的算法,提高數據查詢性能的手段。從磁盤io到內存io的轉變
普通索引,主鍵,唯一,單列/多列索引建索引的幾大原則
1.最左前綴匹配原則,非常重要的原則,mysql會一直向右匹配直到遇到范圍查詢(>、<、between、like)就停止匹配,比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)順序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引則都可以用到,a,b,d的順序可以任意調整。
2.=和in可以亂序,比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意順序,mysql的查詢優化器會幫你優化成索引可以識別的形式
3.盡量選擇區分度高的列作為索引,區分度的公式是count(distinct col)/count(*),表示字段不重復的比例,比例越大我們掃描的記錄數越少,唯一鍵的區分度是1,而一些狀態、性別字段可能在大數據面前區分度就是0,那可能有人會問,這個比例有什么經驗值嗎?使用場景不同,這個值也很難確定,一般需要join的字段我們都要求是0.1以上,即平均1條掃描10條記錄
4.索引列不能參與計算,保持列“干凈”,比如from_unixtime(create_time) = ’2014-05-29’就不能使用到索引,原因很簡單,b+樹中存的都是數據表中的字段值,但進行檢索時,需要把所有元素都應用函數才能比較,顯然成本太大。所以語句應該寫成create_time = unix_timestamp(’2014-05-29’);
5.盡量的擴展索引,不要新建索引。比如表中已經有a的索引,現在要加(a,b)的索引,那么只需要修改原來的索引即可
http://tech.meituan.com/mysql-index.html
http://www.cnblogs.com/cq-home/p/3482101.html
“聚簇”就是索引和記錄緊密在一起。
非聚簇索引 索引文件和數據文件分開存放,索引文件的葉子頁只保存了主鍵值,要定位記錄還要去查找相應的數據塊。
B+是btree的變種,本質都是btree,btree+與B-Tree相比,B+Tree有以下不同點:
每個節點的指針上限為2d而不是2d+1。
內節點不存儲data,只存儲key;葉子節點不存儲指針。
Btree 怎么分裂的,什么時候分裂,為什么是平衡的。
Key 超過1024才分裂B樹為甚會分裂? 因為隨著數據的增多,一個結點的key滿了,為了保持B樹的特性,就會產生分裂,就向紅黑樹和AVL樹為了保持樹的性質需要進行旋轉一樣!
A,atomic,原子性,要么都提交,要么都失敗,不能一部分成功,一部分失敗。
C,consistent,一致性,事物開始及結束后,數據的一致性約束沒有被破壞
I,isolation,隔離性,并發事物間相互不影響,互不干擾。
D,durability,持久性,已經提交的事物對數據庫所做的更新必須永久保存。即便發生崩潰,也不能被回滾或數據丟失。
避免在where子句中對字段進行is null判斷
應盡量避免在where 子句中使用!=或<>操作符,否則將引擎放棄使用索引而進行全表掃描。
避免在where 子句中使用or 來連接條件
in 和not in 也要慎用
Like查詢(非左開頭)
使用NUM=@num參數這種
where 子句中對字段進行表達式操作num/2=XX
在where子句中對字段進行函數操作
由于復合索引的組合索引,類似多個木板拼接在一起,如果中間斷了就無法用了,所以要能用到復合索引,首先開頭(第一列)要用上,比如index(a,b) 這種,我們可以select table tname where a=XX 用到第一列索引 如果想用第二列 可以 and b=XX 或者and b like‘TTT%’
mysql中的in語句是把外表和內表作hash 連接,而exists語句是對外表作loop循環,每次loop循環再對內表進行查詢。一直大家都認為exists比in語句的效率要高,這種說法其實是不準確的。這個是要區分環境的。
如果查詢的兩個表大小相當,那么用in和exists差別不大。
如果兩個表中一個較小,一個是大表,則子查詢表大的用exists,子查詢表小的用in:
not in 和not exists如果查詢語句使用了not in 那么內外表都進行全表掃描,沒有用到索引;而not extsts 的子查詢依然能用到表上的索引。所以無論那個表大,用not exists都比not in要快。
1.EXISTS只返回TRUE或FALSE,不會返回UNKNOWN。
2.IN當遇到包含NULL的情況,那么就會返回UNKNOWN。
在分庫分表時可能會生成重復主鍵 利用自增比例達到唯一 自增1 2,3 等
https://yq.aliyun.com/articles/38438
用過哪些 MQ,和其他 mq 比較有什么優缺點,MQ 的連接是線程安全的嗎,你們公司的MQ 服務架構怎樣的。
根據實際情況說明
我們公司用activeMQ 因為業務比較簡單 只有轉碼功能,而amq比較簡單
如果是分布式的建議用kafka
http://blog.csdn.net/sunxinhere/article/details/7968886
基本都是對數據進行持久化,多盤存儲
集群是保證服務可靠性的一種方式,同時可以通過水平擴展以提升消息吞吐能力。RabbitMQ是用分布式程序設計語言erlang開發的,所以天生就支持集群。接下來,將介紹RabbitMQ分布式消息處理方式、集群模式、節點類型,并動手搭建一個高可用集群環境,最后通過java程序來驗證集群的高可用性。
1. 三種分布式消息處理方式
RabbitMQ分布式的消息處理方式有以下三種:
1、Clustering:不支持跨網段,各節點需運行同版本的Erlang和RabbitMQ, 應用于同網段局域網。
2、Federation:允許單臺服務器上的Exchange或Queue接收發布到另一臺服務器上Exchange或Queue的消息, 應用于廣域網,。
3、Shovel:與Federation類似,但工作在更低層次。
RabbitMQ對網絡延遲很敏感,在LAN環境建議使用clustering方式;在WAN環境中,則使用Federation或Shovel。我們平時說的RabbitMQ集群,說的就是clustering方式,它是RabbitMQ內嵌的一種消息處理方式,而Federation或Shovel則是以plugin形式存在。
https://my.oschina.net/jiaoyanli/blog/822011
https://www.ibm.com/developerworks/cn/opensource/os-cn-RabbitMQ/
LPUSH LPUSHX RPUSH RPUSHX LPOP RPOP BLPOP BRPOP LLEN LRANGE
https://redis.readthedocs.io/en/2.4/list.html
字符串(strings):存儲整數(比如計數器)和字符串(廢話。。),有些公司也用來存儲json/pb等序列化數據,并不推薦,浪費內存
哈希表(hashes):存儲配置,對象(比如用戶、商品),優點是可以存取部分key,對于經常變化的或者部分key要求atom操作的適合
列表(lists):可以用來存最新用戶動態,時間軸,優點是有序,確定是元素可重復,不去重
集合(sets):無序,唯一,對于要求嚴格唯一性的可以使用
有序集合(sorted sets):集合的有序版,很好用,對于排名之類的復雜場景可以考慮https://redis.readthedocs.io/en/2.4/list.html
Redis 的使用要注意什么,講講持久化方式,內存設置,集群的應用和優劣勢,淘汰策略等。
持久化方式:RDB時間點快照 AOF記錄服務器執行的所有寫操作命令,并在服務器啟動時,通過重新執行這些命令來還原數據集。
內存設置 maxmemory used_memory
虛擬內存: vm-enabled yes
3.0采用Cluster方式,
Redis集群相對單機在功能上存在一些限制, 需要開發人員提前了解,
在使用時做好規避。 限制如下:
1) key批量操作支持有限。 如mset、 mget, 目前只支持具有相同slot值的
ke
y執
行批量操作。 對于映射為不同slot值的key由于執行mget、 mget等操作可
能存在于多個節點上因此不被支持。
2) key事務操作支持有限。 同理只支持多key在同一節點上的事務操
作, 當多個key分布在不同的節點上時無法使用事務功能。
3) key作為數據分區的最小粒度, 因此不能將一個大的鍵值對象如
ha
sh、 list等映射到不同的節點。
4) 不支持多數據庫空間。 單機下的Redis可以支持16個數據庫, 集群模
式下只能使用一個數據庫空間, 即db0。
5) 復制結構只支持一層, 從節點只能復制主節點, 不支持嵌套樹狀復
制結構。
Redis Cluster是Redis的分布式解決方案, 在3.0版本正式推出, 有效地解
決了Redis分布式方面的需求。 當遇到單機內存、 并發、 流量等瓶頸時, 可
以采用Cluster架構方案達到負載均衡的目的。 之前, Redis分布式方案一般
有兩種:
·客戶端分區方案, 優點是分區邏輯可控, 缺點是需要自己處理數據路
由、 高可用、 故障轉移等問題。
·代理方案, 優點是簡化客戶端分布式邏輯和升級維護便利, 缺點是加
重架構部署復雜度和性能損耗。
現在官方為我們提供了專有的集群方案: Redis Cluster, 它非常優雅地
解決了Redis集群方面的問題, 因此理解應用好Redis Cluster將極大地解放我
們使用分布式Redis的工作量, 同時它也是學習分布式存儲的絕佳案例。
LRU(近期最少使用算法)TTL(超時算法) 去除ttl最大的鍵值
http://wiki.jikexueyuan.com/project/redis/data-elimination-mechanism.html
http://www.infoq.com/cn/articles/tq-redis-memory-usage-optimization-storage
http://www.redis.cn/topics/cluster-tutorial.html
redis2 和 redis3 的區別,redis3 內部通訊機制。
集群方式的區別,3采用Cluster,2采用客戶端分區方案和代理方案
通信過程說明:
1) 集群中的每個節點都會單獨開辟一個TCP通道, 用于節點之間彼此
通信, 通信端口號在基礎端口上加10000。
2) 每個節點在固定周期內通過特定規則選擇幾個節點發送ping消息。
3) 接收到ping消息的節點用pong消息作為響應。
當緩存使用 持久化使用
基于libevent的事件處理
內置內存存儲方式SLab Allocation機制
并不單一的數據刪除機制
基于客戶端的分布式系統
變化頻繁,具有不穩定性的數據,不需要實時入庫, (比如用戶在線
狀態、在線人數..)
門戶網站的新聞等,覺得頁面靜態化仍不能滿足要求,可以放入
到memcache中.(配合jquey的ajax請求)
Memcached默認使用Slab Allocation機制管理內存,其主要思想是按照預先規定的大小,將分配的內存分割成特定長度的塊以存儲相應長度的key-value數據記錄,以完全解決內存碎片問題。
Redis的內存管理主要通過源碼中zmalloc.h和zmalloc.c兩個文件來實現的。
在Redis中,并不是所有的數據都一直存儲在內存中的。這是和Memcached相比一個最大的區別。
http://lib.csdn.net/article/redis/55323
Redis 的并發競爭問題如何解決,了解 Redis 事務的 CAS 操作嗎。
Redis為單進程單線程模式,采用隊列模式將并發訪問變為串行訪問。Redis本身沒有鎖的概念,Redis對于多個客戶端連接并不存在競爭,但是在Jedis客戶端對Redis進行并發訪問時會發生連接超時、數據轉換錯誤、阻塞、客戶端關閉連接等問題,這些問題均是由于客戶端連接混亂造成。對此有2種解決方法:
1.客戶端角度,為保證每個客戶端間正常有序與Redis進行通信,對連接進行池化,同時對客戶端讀寫Redis操作采用內部鎖synchronized。
2.服務器角度,利用setnx實現鎖。
MULTI,EXEC,DISCARD,WATCH 四個命令是 Redis 事務的四個基礎命令。其中:
MULTI,告訴 Redis 服務器開啟一個事務。注意,只是開啟,而不是執行
EXEC,告訴 Redis 開始執行事務
DISCARD,告訴 Redis 取消事務
WATCH,監視某一個鍵值對,它的作用是在事務執行之前如果監視的鍵值被修改,事務會被取消。
可以利用watch實現cas樂觀鎖
http://wiki.jikexueyuan.com/project/redis/transaction-mechanism.html
http://www.lxweimin.com/p/d777eb9f27df
Raft采用心跳機制觸發Leader選舉。系統啟動后,全部節點初始化為Follower,term為0.節點如果收到了RequestVote或者AppendEntries,就會保持自己的Follower身份。如果一段時間內沒收到AppendEntries消息直到選舉超時,說明在該節點的超時時間內還沒發現Leader,Follower就會轉換成Candidate,自己開始競選Leader。一旦轉化為Candidate,該節點立即開始下面幾件事情:
1、增加自己的term。
2、啟動一個新的定時器。
3、給自己投一票。
4、向所有其他節點發送RequestVote,并等待其他節點的回復。
如果在這過程中收到了其他節點發送的AppendEntries,就說明已經有Leader產生,自己就轉換成Follower,選舉結束。
如果在計時器超時前,節點收到多數節點的同意投票,就轉換成Leader。同時向所有其他節點發送AppendEntries,告知自己成為了Leader。
每個節點在一個term內只能投一票,采取先到先得的策略,Candidate前面說到已經投給了自己,Follower會投給第一個收到RequestVote的節點。每個Follower有一個計時器,在計時器超時時仍然沒有接受到來自Leader的心跳RPC, 則自己轉換為Candidate, 開始請求投票,就是上面的的競選Leader步驟。
如果多個Candidate發起投票,每個Candidate都沒拿到多數的投票(Split Vote),那么就會等到計時器超時后重新成為Candidate,重復前面競選Leader步驟。
Raft協議的定時器采取隨機超時時間,這是選舉Leader的關鍵。每個節點定時器的超時時間隨機設置,隨機選取配置時間的1倍到2倍之間。由于隨機配置,所以各個Follower同時轉成Candidate的時間一般不一樣,在同一個term內,先轉為Candidate的節點會先發起投票,從而獲得多數票。多個節點同時轉換為Candidate的可能性很小。即使幾個Candidate同時發起投票,在該term內有幾個節點獲得一樣高的票數,只是這個term無法選出Leader。由于各個節點定時器的超時時間隨機生成,那么最先進入下一個term的節點,將更有機會成為Leader。連續多次發生在一個term內節點獲得一樣高票數在理論上幾率很小,實際上可以認為完全不可能發生。一般1-2個term類,Leader就會被選出來。
Sentinel的選舉流程
Sentinel集群正常運行的時候每個節點epoch相同,當需要故障轉移的時候會在集群中選出Leader執行故障轉移操作。Sentinel采用了Raft協議實現了Sentinel間選舉Leader的算法,不過也不完全跟論文描述的步驟一致。Sentinel集群運行過程中故障轉移完成,所有Sentinel又會恢復平等。Leader僅僅是故障轉移操作出現的角色。
選舉流程
1、某個Sentinel認定master客觀下線的節點后,該Sentinel會先看看自己有沒有投過票,如果自己已經投過票給其他Sentinel了,在2倍故障轉移的超時時間自己就不會成為Leader。相當于它是一個Follower。
2、如果該Sentinel還沒投過票,那么它就成為Candidate。
3、和Raft協議描述的一樣,成為Candidate,Sentinel需要完成幾件事情
1)更新故障轉移狀態為start
2)當前epoch加1,相當于進入一個新term,在Sentinel中epoch就是Raft協議中的term。
3)更新自己的超時時間為當前時間隨機加上一段時間,隨機時間為1s內的隨機毫秒數。
4)向其他節點發送is-master-down-by-addr命令請求投票。命令會帶上自己的epoch。
5)給自己投一票,在Sentinel中,投票的方式是把自己master結構體里的leader和leader_epoch改成投給的Sentinel和它的epoch。
4、其他Sentinel會收到Candidate的is-master-down-by-addr命令。如果Sentinel當前epoch和Candidate傳給他的epoch一樣,說明他已經把自己master結構體里的leader和leader_epoch改成其他Candidate,相當于把票投給了其他Candidate。投過票給別的Sentinel后,在當前epoch內自己就只能成為Follower。
5、Candidate會不斷的統計自己的票數,直到他發現認同他成為Leader的票數超過一半而且超過它配置的quorum(quorum可以參考《redis sentinel設計與實現》)。Sentinel比Raft協議增加了quorum,這樣一個Sentinel能否當選Leader還取決于它配置的quorum。
6、如果在一個選舉時間內,Candidate沒有獲得超過一半且超過它配置的quorum的票數,自己的這次選舉就失敗了。
7、如果在一個epoch內,沒有一個Candidate獲得更多的票數。那么等待超過2倍故障轉移的超時時間后,Candidate增加epoch重新投票。
8、如果某個Candidate獲得超過一半且超過它配置的quorum的票數,那么它就成為了Leader。
9、與Raft協議不同,Leader并不會把自己成為Leader的消息發給其他Sentinel。其他Sentinel等待Leader從slave選出master后,檢測到新的master正常工作后,就會去掉客觀下線的標識,從而不需要進入故障轉移流程。
RDB 定時快照方式(snapshot): 定時備份,可能會丟失數據
AOF 基于語句追加方式 只追加寫操作
AOF 持久化和 RDB 持久化的最主要區別在于,前者記錄了數據的變更,而后者是保存了數據本身
redis replication redis-migrate-tool等方式
elasticsearch 了解多少,說說你們公司 es 的集群架構,索引數據大小,分片有多少,以及一些調優手段。elasticsearch 的倒排索引是什么。
ElasticSearch(簡稱ES)是一個分布式、Restful的搜索及分析服務器,設計用于分布式計算;能夠達到實時搜索,穩定,可靠,快速。和Apache Solr一樣,它也是基于Lucence的索引服務器,而ElasticSearch對比Solr的優點在于:
輕量級:安裝啟動方便,下載文件之后一條命令就可以啟動。
Schemafree:可以向服務器提交任意結構的JSON對象,Solr中使用schema.xml指定了索引結構。
多索引文件支持:使用不同的index參數就能創建另一個索引文件,Solr中需要另行配置。
分布式:SolrCloud的配置比較復雜。
倒排索引是實現“單詞-文檔矩陣”的一種具體存儲形式,通過倒排索引,可以根據單詞快速獲取包含這個單詞的文檔列表。倒排索引主要由兩個部分組成:“單詞詞典”和“倒排文件”。
elasticsearch 索引數據多了怎么辦,如何調優,部署。
使用bulk API
初次索引的時候,把 replica 設置為 0
增大 threadpool.index.queue_size
增大 indices.memory.index_buffer_size
增大 index.translog.flush_threshold_ops
增大 index.translog.sync_interval
增大 index.engine.robin.refresh_interval
http://www.lxweimin.com/p/5eeeeb4375d4
索引(Index):
在Lucene中一個索引是放在一個文件夾中的。
如上圖,同一文件夾中的所有的文件構成一個Lucene索引。
段(Segment):
一個索引可以包含多個段,段與段之間是獨立的,添加新文檔可以生成新的段,不同的段可以合并。
如上圖,具有相同前綴文件的屬同一個段,圖中共三個段 “_0” 和 “_1”和“_2”。
segments.gen和segments_X是段的元數據文件,也即它們保存了段的屬性信息。
文檔(Document):
文檔是我們建索引的基本單位,不同的文檔是保存在不同的段中的,一個段可以包含多篇文檔。
新添加的文檔是單獨保存在一個新生成的段中,隨著段的合并,不同的文檔合并到同一個段中。
域(Field):
一篇文檔包含不同類型的信息,可以分開索引,比如標題,時間,正文,作者等,都可以保存在不同的域里。
不同域的索引方式可以不同,在真正解析域的存儲的時候,我們會詳細解讀。
詞(Term):
詞是索引的最小單位,是經過詞法分析和語言處理后的字符串。