數據庫不少引擎都是用BTree+做爲索引的數據結構。數據庫索引的主要是爲了更快的查找和定位數據記錄。 若是不考慮性能的話,可使用二叉樹來搜索,根據索引的字段表來實現。 二叉樹根據左右節點的log2n的複雜度的實現。 可是二叉樹存在深度過高的狀況,這樣查找的深度不少,對於特殊的狀況它的複雜都是N, 這樣性能不高。 爲了解決二叉樹的高度問題,提出了M叉樹,這個M叉樹能夠在一個節點上掛多個節點。 可是M叉樹也存在一個問題,對於重建索引或者新建節點的時候,可能存在節點大批量的移動的狀況。php
爲了解決這個問題, 採用旋轉的概念,也就是平衡樹的概念。 經過旋轉樹的邏輯來處理操做。保持節點的平衡html
每一個PHP的變量都會有一個計數器,存在一個zval的變量(在5.6版本以前是24個字節用於存儲),除了包括變量和類型,還增長了2個字節一個is_ref的引用的數據。 第二個是是refcount,表示引用的計數器的數量和數據的邏輯處理。 全部的符號存在一個符號表中,其中每一個符號都有做用域(scope),那些主腳本(好比:經過瀏覽器請求的的腳本)和每一個函數或者方法也都有做用域。mysql
LRU的緩存邏輯的處理操做, LRU的思路一個鏈表的邏輯操做,在鏈表的表頭操做插入, 若是有熱點的數據,在表頭進行插入, 若是鏈表的長度超過了固定的長度, 則擅長鏈表尾部的節點。nginx
這種算法比較簡單,能夠比較緩存高校的節點數據, 可是也可能會存在污染的狀況。 好比一個訪問很集中的狀況,次數不少,可是在必定的時間段裏面它使用低,這時候很容易出現緩存淘汰的操做。web
一、B+樹的層級更少:相較於B樹B+每一個非葉子節點存儲的關鍵字數更多,樹的層級更少因此查詢數據更快;redis
二、B+樹查詢速度更穩定:B+全部關鍵字數據地址都存在葉子節點上,因此每次查找的次數都相同因此查詢速度要比B樹更穩定;算法
三、B+樹自然具有排序功能:B+樹全部的葉子節點數據構成了一個有序鏈表,在查詢大小區間的數據時候更方便,數據緊密性很高,緩存的命中率也會比B樹高。sql
四、B+樹全節點遍歷更快:B+樹遍歷整棵樹只須要遍歷全部的葉子節點便可,,而不須要像B樹同樣須要對每一層進行遍歷,這有利於數據庫作全表掃描。docker
B樹相對於B+樹的優勢是,若是常常訪問的數據離根節點很近,而B樹的非葉子節點自己存有關鍵字其數據的地址,因此這種數據檢索的時候會要比B+樹快。數據庫
分佈式算法解析 主要是經過slab塊來分配內存的算法邏輯, 對於分佈式的算法邏輯操做採用:
餘數算法邏輯 先獲取hashcode的散列值,再除於服務器的臺數,根據餘數獲取服務的節點數
散列算法。先算法memcache的散列值, 並將其分不到0~2^32次方的圓上。 若是超過2^32次方仍是找不到用戶的話, 就將數據保存到第一臺memcache上
環境:Ubuntu16.04 + Core I5 4核 + 8G內存 PHP7.0.10 腳本:ab -c 100 -n 10000 http://127.0.0.1:9501/ Connection Times (ms) min mean[+/-sd] median max Connect: 0 0 0.2 0 2 Processing: 0 9 9.6 6 96 Waiting: 0 9 9.6 6 96 Total: 0 9 9.6 6 96
使用wrk來測試性能的狀況,看下是否能夠處理的能力操做 wrk -t4 -c8 -d60s http://192.168.1.10:8812/hello.php
wrk -t4 -c8 -d60s http://192.168.1.10:8812/hello.php
主要是採用多路複用IO的邏輯來實現,而多路複用的IO是異步非阻塞的操做。 對於要回調的時間寫入到紅黑樹樹,這個是自由平等的二叉樹,能夠保證搜索的速度控制再logN的時間複雜度實現
深刻淺出網絡編程與Swoole內核,查看
swoole協程原理是由事件驅動和棧切換兩步共同完成的實現的。
http的三次握手和四次揮手
四次揮手主要是客戶端發送我要中斷,服務端接受到指令的時候,發送你的數據我已經收到,而且發送我也沒有數據要發送了, 最後客戶端發送我已經收到了。
Paxos 算法應該能夠說是 ZooKeeper 的靈魂了。可是,ZooKeeper 並無徹底採用 Paxos算法 ,而是使用 ZAB 協議做爲其保證數據一致性的核心算法。另外,在ZooKeeper的官方文檔中也指出,ZAB協議並不像 Paxos 算法那樣,是一種通用的分佈式一致性算法,它是一種特別爲Zookeeper設計的崩潰可恢復的原子消息廣播算法。
ZAB(ZooKeeper Atomic Broadcast 原子廣播) 協議是爲分佈式協調服務 ZooKeeper 專門設計的一種支持崩潰恢復的原子廣播協議。 在 ZooKeeper 中,主要依賴 ZAB 協議來實現分佈式數據一致性,基於該協議,ZooKeeper 實現了一種主備模式的系統架構來保持集羣中各個副本之間的數據一致性。
對於內網的域名的解析主要仍是經過負載均衡的處理的方式。經過訪問DNS的域名,而後配置多個ip輪詢做爲負載均衡的策略,這樣一個域名的方法,能夠解析多個IP
事務隔離是數據庫事務特徵中的一種。 ACID,原子性,一致性,隔離性,持久性。
隔離機制主要是解決事務讀寫等級的狀況。 通常常見的事務有問題有,
讀未提交:能夠讀到未提交的數據。這是能夠出現髒讀,幻讀
讀提交:能夠讀到提交的數據。這個主要是讀取數據的快照,能夠解決髒讀的問題,不可以解決不可重讀的問題。 能夠在讀取提交的時候,同時進行更新了。 這樣就不可以解決不可重讀的問題。
可重讀:主要是針對不可重讀的問題,在讀取的時候不可以進行更新操做。 也是mysql默認的事務級別。
串行化是事務的最高級別,就是一個個排隊的執行。 性能比較低。
服務的高可用主要是來解決服務在使用過程當中的遇到問題可以自動容錯和快速的恢復,同時系統隨着業務增加也能夠自動的擴展。
架構的常見問題:單系統的問題和系統間的問題。
單機的處理問題主要包括, 慢查詢的問題,影響執行的性能甚至影響鎖表和鎖庫,造成讀取的I/O阻塞的,從而影響其性能。
大事務問題:事務執行的時間性阻塞,還有服務的請求超時和重試的問題。以及一些代碼影響的系統的執行性能的問題,致使系統不可用或者響應時間太長。
除了單系統的問題,還有系統間的問題。
檢查的清單
大分類 | 小分類 | check項目 |
---|---|---|
基礎組件依賴 | 緩存 | 掛了是否可用,跟其餘系統共用 |
MYSQL | 跟其餘系統共用,慢查詢,大事務,鏈接池監控情況,大表,讀寫分類,主從延時敏感 | |
MQ | 掛了是否可用, 依賴於消息發送的順序 | |
日誌 | 創建日誌不超過30%,使用日誌的性能和穩定性 | |
其餘組件 | 是否有監控的系統來監控 | |
依賴於外部環境 | 依賴於外部的上下游的狀況 | |
核心接口 | 性能問題 | |
JVM | 基本配置 | 堆棧的配置, 線程的監控和報警, 批量更新和緩存操做 |
容量預估 | 高峯期的CPU load,高峯期的內存, 高峯期的磁盤IO,高峯期的網卡,是否三倍冗餘 |
表拆分,大表拆成小表主要是解決減小表記錄查詢的時間,同時提升數據庫的吞吐率,這就是所謂的分表
分表只是解決了查詢性能和效率的問題,但對於數據庫的併發處理無法帶來質的提高, 面對高併發的讀寫, 當數據庫master服務器沒法承載寫的操做壓力時候,無論如何擴展slave服務器都沒有意義。 因此要換個思路對於庫進行拆分,提升庫的寫入能力,這就是所謂的分庫。
分表包括水平拆分和垂直拆分,以及分區拆分
水平拆分的維度包括
難點在事務的處理。
Step1:按照新舊分片規則,對新舊數據庫進行雙寫。
Step2:將雙寫前按照舊分片規則寫入的歷史數據,根據新分片規則遷移寫入新的數據庫。
Step3:將按照舊的分片規則查詢改成按照新的分片規則查詢。
Step4:將雙寫數據庫邏輯從代碼中下線,只按照新的分片規則寫入數據。
Step5:刪除按照舊分片規則寫入的歷史數據。
要避免在一個事務中同時修改數據庫db0和數據庫db1中的表,由於操做起來很複雜,對效率也會有必定的影響。請參考第三章的內容。
要避免在一個事務中同時修改數據庫db0和數據庫db1中的表,由於操做起來很複雜,對效率也會有必定的影響。請參考第三章的內容。
zabbix,是一個web的界面提供分佈式系統監控以及網絡監視功能企業級的開源解決方案
zabbix能夠收集各類網絡參數, 保證系統的安全運營, zabbix支持兩種方式,一種是zabbix server, 一種是zabbix agent。能夠對端口監控,查看遠程服務器和網絡監視的狀態。
zenoss Zenoss Core是開源企業級IT管理軟件-是智能監控軟件,他容許IT管理員依靠單一的WEB控制檯來監控網絡架構的狀態和健康度。Zenoss Core同時也是開源的網絡與系統管理軟件。
HTOP 能夠很清晰的查看網絡的服務器狀況和性能的狀況。 包括IO,負載等數據狀況。
第三方服務器: 監控寶,能夠主要是經過探針的方式,來監控多種服務。 不過對於鏈路監控支持的不是很好。
全鏈路監控,也是系統在使用的。 Zipkin全鏈路監控,查看
經過統一的trace id來監控總體的鏈路服務狀況,而且把這種服務運用平常的開發報警和日誌的問題定位之中。
監控的主要內容:
Redis是輕量級的消息隊列,寫入和出隊列性能都比較高,
RabbitMQ是一個由erlang開發的AMQP(Advanced Message Queue )的開源實現的產品,RabbitMQ是一個消息代理,從「生產者」接收消息並傳遞消息至「消費者」,期間可根據規則路由、緩存、持久化消息。「生產者」也即message發送者如下簡稱P,相對應的「消費者」乃message接收者如下簡稱C,message經過queue由P到C,queue存在於RabbitMQ,可存儲儘量多的message,多個P可向同一queue發送message,多個C可從同一個queue接收message
Redis緩存之穿透、雪崩、熱Key問題,查看
產生的緣由: 用戶消費的數據遠大於生產的數據,如在突發的事件請求的數據大於遠超過要寫入的數據。就會形成熱數據。
咱們通常採用緩存+過時時間來解決這個問題, 可是過時後容易集中打到緩存中。 集中出現的兩個問題:
若是出現以上的問題, 就會出現緩存失效,大量的請求就會繞過redis緩存,而直接查詢後端服務的壓力,包括服務器和數據庫的壓力。
解決的方案:
場景描述:緩存查詢某個key的時候會從數據庫中來讀取,若是緩存層查詢不到就會到查詢存儲層去讀取數據,而後就失去了緩存的意義,在必定的程度上影響數據庫壓力。 解決方案: 對於不存在的key放到布隆過濾器(hash)的數據結構,把全部的可能存在的數據hash到一個bitmap裏面, 對於不存在的數據會被這個bitmap進行過濾。若是查詢一個數據爲空, 對於爲空的數據,咱們也會進行緩存的操做。 不過設置時間不超過5分鐘。布隆過濾器重要是解決一個排序的數據,按照位來存儲,其實構建的一個巨大的稀疏矩陣,對於數據過濾很是重要,對於遍歷數據的時候若是出現0,則表示沒有合適的數據,並進行過濾使用
這種是來自於key的大面積失效,帶來的後端服務查詢數據的壓力,從而致使數據庫的壓力。 一個簡單的方法對於緩存的值都加上一個隨機值,這樣在訪問的時候,不容易出現大面積的失效,從而查詢後端的服務。
同時咱們能夠在redis和數據庫之間增長互斥鎖(使用互斥鎖(mutex key))或者查詢隊列,來緩解對數據的壓力。 對於查詢比較大的狀況,能夠經過隊列的等待來解決。
public String get(key) {
String value = redis.get(key);
if (value == null) { //表明緩存值過時
//設置3min的超時,防止del操做失敗的時候,下次緩存過時一直不能load db
if (redis.setnx(key_mutex, 1, 3 * 60) == 1) { //表明設置成功
value = db.get(key);
redis.set(key, value, expire_secs);
redis.del(key_mutex);
} else { //這個時候表明同時候的其餘線程已經load db並回設到緩存了,這時候重試獲取緩存值便可
sleep(50);
get(key); //重試
}
} else {
return value;
}
}
複製代碼
增長work_rlimit_nofile和worker_connections數量,並禁用keepalive_timeout。
保持處理的鏈接數,並禁用keepalive的處理, nginx的配置參數主要集中在worker進程數量,使用的異步事件IO創建的鏈接數。也能夠對nginx和php-fpm的優化配置,包括nginx 啓動以後,對於php進程不夠,能夠設置pm.max_children來設置其進程數量。
php-fpm的調參數:動態和靜態的狀況下啓動的線程和進程的數量的狀況。
思路
內核層面:加大鏈接數,加快tcp回收
mysql層面:增大鏈接數, 關閉磁盤noatime, 使用SSD硬盤
php層面:用長鏈接,節省鏈接數 用內存緩存(memcached/redis),減輕mysql壓力
注意 內存緩存適用於緩存複雜的sql查詢。由於php與memcached也要創建tcp鏈接,因此簡單的sql查詢不須要用緩存。
對在高併發的狀況下,保持性能的高可用。 對於這樣的狀況下,nginx 層面根據機器的狀況下計算下nginx的配置的worker數量和connections的數量,而且保證進程服務的穩定。
PHP主要是接受Nginx的fastcgi的報文。是不錯的選擇哦。
限制流量的大小,下降請求的流量,降級的目的很降級的目的比較簡單(保證基礎服務的可用,保證核心業務的可用,對於輔助的業務不進行訪問正常), 第一個是保障服務器基本可用,第二個是保障服務的核心服務可用。降級是怎麼一個思路呢?通常降級的每一個策略都是針對一個場景,預想特定場景下須要要解決什麼問題;而後再梳理在這個場景下須要保留哪些核心基本服務;
限流:限流常見的是漏桶算法和令牌算法。思路就是在把全部的流量是一個池子,流動的速率是穩定的,孔的高度也是穩定的。漏桶算法可以保證請求的負載時間長, 即每秒可以處理的請求數量。
令牌算法:令牌桶算法也是有一個桶,可是桶不漏,桶裏面放了一些令牌,每來一個請求就在桶裏拿一個令牌,若是沒有令牌它就能夠等待,令牌滿了就再也不往裏面加令牌。這樣方法基本上也能夠達到一個限流的目的。令牌桶算法和漏桶算法的一個顯著區別是漏桶算法在後端取請求量時,基本上漏的速率是同樣的,可是令牌桶算法中後端部分能夠有突發請求,若是桶滿了,能夠將桶裏全部令牌都拿走。
降級: 通常狀況下,系統上線以後總會遇到一些不穩定狀況,好比 redis 掛掉,甚至後端數據庫 My SQL 掛掉。當出現不穩定狀況以後,系統如何保證繼續提供這些服務。
對於作了好了基本的策略,咱們進一步採用, 線上的保證其穩定性。 Code Review: 來對代碼的審覈,提升代碼的質量,而且對代碼的進行整理。
壓測: 壓測的目的第一保持系統的穩定性。在高併發的是時候也能夠保持系統的穩定性, 由於在必定的流量的基礎上。檢查性能的抗壓能力, 檢查系統的可以承受的QPS
灰度: 灰度目的是小範圍試錯,儘可能發現問題。只讓某個地區的人先訪問其特性, 遇到問題的及時反饋
監控: 自動化及時發現問題。監控的問題發現的事情。
全鏈路的監控服務,來保持系統的穩定性。
Nginx的處理,
opcache 一方面提升了php的性能,可是另外一方面,對於線上發版原本說,很容易出現緩存一直存在的狀況。 考慮解決該問題的方式,主要集中在兩個方面, 一個是設置opcache的失效時間,另外一個是經過手動或者自動更新文件,清理opcache的緩存。 對於能夠時間使用調用opcache_reset 來重置緩存,也可使用發版本的rsync來更新同步緩存。