導讀知識點列表一、redisredis應用場景stringhashset:去重zset:排行榜list:(阻塞隊列、消息通信)HyperLogLog:大量統計(....
知識點列表
一、redis
- redis
- 應用場景
- string
- hash
- set:去重
- zset: 排行榜
- list:(阻塞隊列、消息通信)
- HyperLogLog:大量統計(非精確)
- 內部數據結構
- dict:key[string] VS value (redis obj);拉鏈法解決沖突(同php);裝載因子(哈希表已保存節點數量 / 哈希表大小)超過預定值自動擴充內, 引發(增量式)rehashing
- 根據ht[0]創建一個比原來size大一倍(也可能減少)的hashtable,
- 重新計算hash和index值,根據rehashindex逐步操作
- 到達一定閾值(ht[0]為空)操作停止
- 期間響應客戶端
- 寫操作:寫到新的ht[1]
- 讀操作:先讀ht[0],再讀ht[1]
- sds:simple dynamic string
- string的底層實現為sds,但是string存儲數字的時候,執行incr decr的時候,內部存儲就不是sds了。
- 二進制安全binary safe(5種類型的header falgs得到具體類型,進而匹配len和alloc)
- robj:redis object,為多種數據類型提供一種統一的表示方式,同時允許同一類型的數據采用不同的內部表示,支持對象共享和引用計數。
- sds
- string
- long
- ziplist
- quicklist
- skiplist
typedef struct redisObject { unsigned type:4;【OBJ_STRING, OBJ_LIST, OBJ_SET, OBJ_ZSET, OBJ_HASH】 unsigned encoding:4【上述type的OBJ-ENCODING _XXX常量,四個位說明同一個type可能是不同的encoding,或者說同一個數據類型,可能不同的內部表示】; unsigned lru:LRU_BITS; /* lru time (relative to server.lruclock) */ int refcount; void *ptr【真正指向的數據】; } robj
- OBJ_ENCODING_
- string
- OBJ_ENCODING_RAW,代表sds ,原生string類型
- OBJ_ENCODING_INT,long類型
- OBJ_ENCODING_EMBSTR ,嵌入
- OBJ_HASH
- OBJ_ENCODING_HT,表示成dict
- OBJ_ENCODING_ZIPLIST,hash用ziplist表示
- OBJ_SET
- OBJ_ENCODING_INTSET,表示成intest
- config
- set-max-intset-entries 512【是整型而且數據元素較少時,set使用intset;否則使用dict】
- OBJ_ZSET
- OBJ_ENCODING_SKIPLIST,表示成skiplist
- 思想:多層鏈表,指針來回查找,插入和更新采取隨機層數的方法來規避
- config
- zset-max-ziplist-entries 128
- zset-max-ziplist-value 64
- OBJ_LIST
- OBJ_ENCODING_QUICKLIST
- config
- list-max-ziplist-size -2
- list-compress-depth 0
- 內部結構實現
- string
- hash(兩種encoding,根據下面的config)
- ziplist
- dict
- config
- hash-max-ziplist-entries 512【注意單位是“對兒”】
- hash-max-ziplist-value 64【單個value超過64】
- set
- zset
- list
- quicklist
- 定義:是一個ziplist型的雙向鏈表
- 壓縮算法:LZF
- zset如何根據兩個屬性排序?比如根據id和age
- 可以用位操作,把兩個屬性合成一個double
- 用zunionstore合并存儲為新的key,再zrange
- redis是如何保證原子性操作的?
- 因為他是tm單線程的!(ps:mysql是多線程)
- 在并發腳本中的get set等不是原子的~
- 在并發中的原子命令incr setnx等是原子的
- 事務是保證批量操作的原子性
- 主從復制過程:
- 從服務器向主服務器發送sync
- 主服務器收到sync命令執行BGSAVE,且在這期間新執行的命令保存到一個緩沖區
- 主執行(BGSAVE)完畢后,將.rdb文件發送給從服務器,從服務器將文件載入內存
- BGSAVE期間到緩沖區的命令會以redis命令協議的方式,將內容發送給從服務器。
- 特性:
- 單線程,自實現(event driver庫,見下面四個io多路復用函數)
- 在/src/ae.c中:宏定義的方式
/* Include the best multiplexing layer supported by this system. * The following should be ordered by performances, descending. */ #ifdef HAVE_EVPORT #include "ae_evport.c" #else #ifdef HAVE_EPOLL #include "ae_epoll.c" #else #ifdef HAVE_KQUEUE #include "ae_kqueue.c" #else #include "ae_select.c" #endif #endif
- io多路復用,最常用調用函數:select(epoll,kquene,avport等),同時監控多個文件描述符的可讀可寫
- reactor方式實現文件處理器(每一個網絡連接對應一個文件描述符),同時監聽多個fd的accept,read(from client),write(to client),close文件事件。
- 備份與持久化
- rdb(fork 進程dump到file,但是注意觸發節點的覆蓋問題,導致數據不完整)
- 手動 save bgsave
- 自動 conf:save 900 1 save 300 10 save 60 10000 dbfilename dump.rdb
- 優點:對服務進程影響小,記錄原數據文件方式便于管理還原
- 缺點:可能數據不完整
- aof(類似binlog)
- appendfsync no
- appendfsync everysec
- appendfsync always (每執行一個命令)
- 優點:數據最完整,支持rewrite
- 缺點:文件相對rdb更大,導入速度比rdb慢
- 過期策略:
- 定時過期:時間到了立即刪除,cpu不友好,內存友好。
- 惰性過期:訪問時判斷是否過期:cpu友好,內存不友好
- 定期過期:expires dict中scan,清除已過期的key。cpu和內存最優解
- 內存淘汰機制
- 127.0.0.1:6379> config get maxmemory-policy
1) "maxmemory-policy"2) "noeviction"127.0.0.1:6379>
- noeviction:新寫入時回報錯
- allkeys-lru:移除最近最少使用的key
- allkeys-random:隨機移除某些key
- volatile-lru:設置了過期時間的key中,移除最近最少使用
- volatile-random:不解釋
- volatile-ttl:設置類過期時間的鍵中,有更早過期時間的key優先移除
- redis隊列不足之處
- 隊列可能丟東西
- 比如redis掛了,producer沒有停止,但是隊列數據無法寫入(除非同步落地到mysql)
- 隊列的consumer 需要手動處理commit協議
- 如果consumer處理完,表示真正完成
- 如果沒有處理完?放回隊列?直接丟棄?
- 事件重放機制不支持
- 比如consumer消費錯了,那能不能將隊列回放呢再次處理呢?
- 隊列最大長度及過期時間
- 如果producer遠大于consumer,撐爆了怎么辦
- 如果comsumer 一直沒有處理,producer的數據如何處理
- exactly once
- 單機分布式鎖沒問題,集群情況下不靠譜
- vs memcache
- memcached
- 優勢
- 多線程(listen & woker),利用多核
- round robin
- cas(check and set,compare and swap)
- 劣勢
- cache coherency、鎖
- key大小有限制(1M)
- 特點
- 內存預分配:slab trunk
- redis
- 優勢:
- 自己封裝了一個AEEvent(epoll select kqueue),io多路復用
- 豐富的數據結構(對內 對外)
- 良好的持久化策略(rdb aof)
- 單機可部署多實例,利用多核
- 劣勢:
- 排序、聚合cpu密集操作會等影響吞吐量
- key 大小最大為1g
- more | other
- redis ziplist與普通雙向鏈表的區別:普通的鏈表每一項都占用獨立的一塊內存,各項之間用地址指針(引用)連接起來,這樣會導致大量碎片。而ziplist是將表中每項放在前后連續地址空間內,而且對值存儲采取變長編碼。
- redis msetnx對應的del,可以采取lua腳本保證get del的原子性
- redis 單線程如何實現阻塞隊列?
- 阻塞是阻塞client,又不是阻塞server,server不發數據,client不就阻塞住了,當client想要阻塞在某個key上,server會把這個client放到一個block list里,等key發生變化,就send數據給client。
- redis 阻塞隊列的時間設置實現?
- blocklist里只存了列表,這個timeout存在連接上,靠serverCron來遍歷檢測,每次遍歷5個,
- 高性能的方案是小堆或者紅黑樹或者時間輪實現的定時器結構,epoll wait那塊timeout參數就設置成下次超時時間
- 每次poll loop里除了處理io事件,再把定時器的數據結構里處理下,堆和紅黑只要檢測到一個未超時就可以break了,時間輪這是當前槽都觸發了就行
- 每次檢測5個這種比較折中,因為他場景不是大量并發的服務器,rds cli的連接數量畢竟使用者內部可控,而且不需要精確打擊,只要保障相對能及時清理就行,redis的網絡部分相對比較簡單,業務場景可控,足夠了
- redis集群情況下如何做到兩個key必hash到一個節點?用{}
二、MySql
- mysql
- 索引
- 物理存儲
- 聚簇索引
- 非聚簇索引
- 數據結構
- B 樹
- hash
- fulltext
- R-tree
- 邏輯角度
- 唯一索引 unique
- 普通索引index
- 主鍵索引 primary key
- 全文索引 full index(myisam)
- 復合索引 (最左前綴原則)
- 類似 where a and b and c a b c 問題
- 聯合索引(a,b,c) 能夠正確使用索引的有(a=1), (a=1 and b=1),(a=1 and b=1 and c=1)(b=1 and c =1
- 引擎類型
- myisam
- innodb
- 區別:
- myisam采用非聚集索引,innodb采用聚集索引
- myisam索引myi與數據myd文件分離,索引文件僅保存數據記錄指針地址。
- myisam的主索引與輔助索引在結構上沒區別,而innodb不一樣:innodb的所有輔助索引都引用主索引作為data域。
- innodb支持事務,行級鎖。myisam不行。
- innodb必須有主鍵,而myisam可以沒有。


- 數據被邏輯的存在tablespace,extend(區)中有多個page,page(默認16kb)里放row(每一行,大概每個page放2-200行記錄)
- .frm:tables format
- .ibd:table data & associated index data
- ubunut的frm文件和ibd文件可在目錄root@udev:/var/lib/mysql# ls中查看,下圖為innodb行格式,由下到上,均向上兼容

- Antelope 羚羊 對存放bolb或者大varchar存儲極長的數據時,將行數據的前768字節存儲在數據頁中,后面通過偏移量指向溢出頁。
- compact 緊湊的
- redundant 多余的
- Barracuda 梭魚
- antelope對存放blob的數據完全溢出,在數據頁中只存在20個字節的指針,實際數據放在bolb page
- compressed
- dynamic
- more
- myisam
- frm(與innodb通用),在磁盤的datadir文件
- myi
- myd
- 事務
- 原子性atomicity
- 一致性consistency
- 隔離性lsolation
- 持久性durability
- 分表數量級
- 單表在500w左右,性能最佳。BTREE索引樹 在3-5之間
- 隔離級別
- 事務的隔離性是數據庫處理數據的基礎之一,隔離級別是提供給用戶在性能和可靠性做除選擇和權衡的配置項目,以下四種情況都有一個前提(在同一個事物中)
- read_uncommited:臟讀,不加任何鎖,可能讀到未提交的行,見下圖

- read_commit:不可重復讀,只對記錄加記錄鎖,而不會在記錄間加間隙鎖。所以允許新的記錄插入到被鎖定記錄的附近,所以多次使用查詢語句時,可能得到不同的結果,non_repeatable_read,見下圖

- repeatable_read【默認級別】:幻讀,返回第一次的查詢的快照(不會返回不同數據),但是可能有幻讀(phantom read),雖然第一次是個空,但是在session2中提交之后,發現已經有了這條數據。見下圖

- serialize:解決了幻讀
- 索引機制(算法)
- hash
- b tree(m階b tree)
- 所有數據保存在葉子節點,有k個子樹的中間節點包含有k個元素
- 所有葉子節點包含了全部的元素信息,及指向這些元素記錄的指針,且葉子節點本身依關鍵字的大小自小而大順序鏈接
- 所有的中間節點元素都同時存在于子節點,在子節點元素中都是最大(或最小)元素(或者說:每一個父節點的元素都出現在子節點中,是子節點的最大或者最小元素)
- 插入的元素,要始終保持最大元素在根節點中,再次說:所有的葉子節點包含了全量元素信息。每個葉子節點都帶有指向下個節點的指針,形成了有序鏈表

- b-tree【不要念成b減tree】
- 內存操作(單一節點數量很多時,注意并不比二叉查找樹數量少,只是速度比硬盤要快)
- 自平衡
- 左旋、右旋
- mongoDB用的是balance tree
- 特點(m階的B樹)
- 根節點至少有兩個子女
- 每個中間節點都包括k-1個元素和k個孩子(m/2<=k<=m)
- 每個葉子節點都包括k-1個元素,(m/2<=k<=m)
- 所有的葉子節點位于同一層
- 每個節點中的元素從小到大排序,節點當中k-1個元素正好是k個孩子包含元素的值域劃分
- b 與b-區別
- b 中間節點沒有衛星數據,而b-tree有衛星數據(可以理解為key data的二維數組),所以前者同樣大小可以容納更多的節點元素。這樣又導致了b 比b更“矮胖”,更進一步減少了io查詢次數。很好的解釋了下面這句話:在cluster index(聚集索引中),葉子節點直接包含衛星數據;在非聚集索引中nonclustered index中,葉子節點帶有指向衛星數據的指針。
- b-只要查找到匹配元素,直接返回,網絡匹配元素處理中間節點還是葉子節點。而b 查詢必須查找到葉子節,相對于b-,b 無需返回上層節點重復遍歷查找工作,所以得出b-查找并不穩定,而b 是穩定的。
- 針對范圍查詢,b-需要n次中序遍歷,而b 只需要通過子節點鏈表指針遍歷即可。
- 鎖
- 種類
- optimistic lock樂觀鎖(并非真正的鎖,先嘗試在,再更改,loop and try)
- 特點:不會真死鎖,一定條件下有較高的沖突頻率和重試成本,但是相對悲觀可以有更好的并發量
- pessimistic lock悲觀鎖(先占有,再修改,再釋放)
- 粒度劃分
- 行鎖
- 表鎖
- 意向鎖 intention lock(表級鎖)
- 場景:A對表中一行進行修改,B對整個表修改。如果沒有以下的兩個鎖,B將對全表掃描是否被鎖定。反之,A可以對某行添加意向互斥鎖(表級),然后再添加互斥鎖(行級),然后B只需要等待意向互斥鎖釋放)
- 意向共享鎖
- 意向互斥鎖
- 共享鎖shard lock 讀鎖(行鎖)
- 排它鎖exclusive lock 寫鎖(行鎖)
- 鎖的算法
- record lock:加到索引記錄上的鎖,如果通過where條件上鎖,而不知道具體哪行,這樣會鎖定整個表
- gap lock:某個區間的鎖定,對索引記錄中的一段連續區域的鎖。
- next-key lock:上兩者的結合
- 死鎖:

- 注意區分 deadlock VS lock wait timeout
- 分庫分表
- 主從
- ACID
- 覆蓋索引(復合索引)
- 定義:包含兩個或多個屬性列的索引稱為復合索引。如果查詢字段是普通索引,或者是聯合索引的最左原則字段,查詢結果是聯合索引的字段或者是主鍵。這種就不必通過主鍵(聚集索引再次查詢)
- 目的:減少磁盤io,不用回表
- b 樹索引
- 聚集索引cluster index 一般為primary key
- 定義:按照每張表主鍵構建一棵B TREE,葉子節點放的整張表的行記錄數據
- 與之相對應的是輔助索引(secondary index)
- innodb存儲引擎支持覆蓋索引,即從輔助索引中可以查到查詢記錄,而不需要查詢聚集索引中的記錄。
- b平衡樹 樹索引

CREATE TABLE users( id INT NOT NULL, first_name VARCHAR(20) NOT NULL, last_name VARCHAR(20) NOT NULL, age INT NOT NULL, PRIMARY KEY(id), KEY(last_name, first_name, age) KEY(first_name)
- 一張表一定包含一個聚集索引構成的b 樹以及若干輔助索引構成的b 樹
- 每次給字段建一個索引,字段中的數據就會被復制一份出來。用于生成索引,(考慮磁盤空間)。不管何種方式查表,最終都會利用主鍵通過聚集索引來定位到數據。聚集索引(主鍵)是通往真實數據的唯一出路。
- 輔助索引:非聚集索引都可以被稱作輔助索引,其葉子節點不包含行記錄的全部數據,僅包含索引中的所有鍵及一個用于查找對應行記錄的【書簽(即主鍵或者說聚集索引)】,下面兩個圖為輔助索引(first_name,age)以及通過主鍵再次查找的過程


- 聯合索引:與覆蓋索引沒有區別,或者理解為覆蓋索引是聯合索引的最優解(無需通過主鍵回表)。
- explain
- extra
- using index :condition(用了索引,但是回表了)
- using where :uning index(查詢的字段在索引中就能查到,無需回表)
- using index condition:using filesort(重點優化:表明查到數據后需要再進行排序,盡量利用索引的有序性。)
- using where:using index
- type(連接類型:join type),以下逐步增大
- system 系統表,磁盤io忽略不計(有些數據就已經在內存中)
- const 常量連接(加了where條件限制,命中主鍵pk或者唯一unique索引)
- eq_ref 主鍵索引或者非空唯一索引、等值連接;如果把唯一索引改為普通索引 等值匹配,可能type只為ref,因為可能一對多
- range 區間范圍 between and;where in,gt lt;(注意必須是索引)
- index 索引樹掃描,即需要掃描索引上的全部數據,比如innodb的count
- all 全表掃描
- select * 與索引(看主要命中條數與總條數,如果相近,用不到索引,就全回表了,如果是一定范圍,那就是range use indexcondition)
- rows(粗略統計,不是精確)
- 其他:
- varchar為啥為65535?compact行記錄的第一個字段為變長字段長度列表,為2個字節16位。參考
- 一個表最多多少行?1023,具體也是看行格式的數據結構即可,參考上文的參考鏈接。
- 為什么建議給表加主鍵?主鍵的作用是把數據格式轉為索引(平衡樹)
- 聯合索引在b 樹中如何存儲?
- 為什么索引不直接用二叉查找樹,要用b樹,b 樹?主要考慮減少磁盤io(考慮磁盤物理原理及局部性與磁盤預讀的特性:)
- myisam和innodb必須有主鍵嗎?innodb必須有,數據文件需要按照主鍵聚集,如果沒有innodb會自動生成。
三、算法&數據結構
- 最小堆:根節點為最小值,且節點比其他孩子小
- 平衡樹(avl 紅黑樹)
- 最大堆:根節點為最大值,且節點比其他孩子大
- sikplist
- hash
- hash 碰撞原因
- hash 碰撞解決方案
- 拉鏈,塞到鏈表里(想到了php max_input_vars)
- 開放尋址,一直找..
- 線性探測
- 二次探測再散列
- 偽隨機數
- 再hash
- 給定數值n,判斷n是斐波那契數列的第幾項?寫算法
- 反轉列表如A->B->C->D 到A->D->C->B
- 插入排序
- 數組與鏈表區別與聯系
- 鏈表操作
- 單鏈表刪除
p->next=p->next->next; if(head->next===null){ head=null }
new_node->next=p->next; p->next=new_node if(head===null){ head=new_node; }
- 應用問題
- 如何實現一個LRU功能?【雙向鏈表】
- 如何實現瀏覽器前進后退功能?【兩個棧】
四、設計模式
- 設計模式
static private $instance; private $config; private funciton __construct($config){ $this->config=$config; } private funciton __clone(){ } static public function instance($config){ if(!self::$instance instanceof self){ self::$instance=new self($config); } return self::$instance; }}
- 簡單工廠(switch case include new return )
{ public function makeModule($moduleName, $options) { switch ($moduleName) { case Fight: return new Fight($options[0], $options[1]); case Force: return new Force($options[0]); case Shot: return new Shot($options[0], $options[1], $options[2]); } } } # 使用工廠方式 001 class Superman { protected $power; public function __construct() { // 初始化工廠 $factory = new SuperModuleFactory; // 通過工廠提供的方法制造需要的模塊 $this->power = $factory->makeModule(Fight, [9, 100]); // $this->power = $factory->makeModule(Force, [45]); // $this->power = $factory->makeModule(Shot, [99, 50, 2]); /* $this->power = array( $factory->makeModule(Force, [45]), $factory->makeModule(Shot, [99, 50, 2]) ); */ } }# 使用工廠方式 002 class Superman { protected $power; public function __construct(array $modules) { // 初始化工廠 $factory = new SuperModuleFactory; // 通過工廠提供的方法制造需要的模塊 foreach ($modules as $moduleName => $moduleOptions) { $this->power[] = $factory->makeModule($moduleName, $moduleOptions); } } } // 創建超人 $superman = new Superman([ Fight => [9, 100], Shot => [99, 50, 2]
- 門面模式
- 對客戶屏蔽子系統組件,減少子系統與客戶之間的松耦合關系
五、正則表達式
- 正則表達式
- 應用場景
- 范匹配
- 模版引擎
- 詞法分析器(lex)
- 常見正則
六、PHP
- php
- 代碼解釋過程(大多的非編譯語言)
- lexical詞法分析,輸入為源代碼,輸出為token
- 語法分析 工具為文法(LALR),輸出為表達式,7.0為AST,涉及:
- 注釋
- 分號 & 分隔符
- 變量
- 常量
- 操作數
- 類型檢查、關鍵字處理、導入,輸出為中間代碼。工具為選定的的編譯器優化工具
- 中間代碼生成(Opcodes)
- 機器碼生成(編譯語言)
- session共享配置
- phpunit用法
- cookie購物車和session購物車的實現
- 弱類型實現
- 代碼規范
- 自動化:sonarquebe jenkins
- 單元測試
- php進程間如何通信
- 信號量
- 消息隊列
- 管道
- socket
- 共享內存
- php并發模型
- 變量底層存儲結構
- 常用的數組函數(列出10個)
- array_combine(前面數組作為其鍵,后面數組做為其值)
- array_merage(合并兩個數組,后面覆蓋前面,但數字索引會重新索引,不會覆蓋)
- array_multisort
- php垃圾回收機制(gc)
- zend.enable_gc php.ini
- gc_enable() funciton
- 把session放入redis里面還會觸發類似文件的state session
- session.gc_probability (default 1)
- session.gc_divisor (default 100)
- session.gc_maxlifetime(單位秒)
- session.cookie_lifetime(單位秒,0表示直到關閉瀏覽器)
- session.save_path
- session_write_close (顯示關閉,后期使用需要顯示開啟)
七、操作系統
- 操作系統
- 多線程
- 多進程
- 協程的理解
- socket和管道的區別
- 進程間通信手段
- 共享內存
- rpc
- 管道
- 線程間通信手段
- 讀寫進程數據段
八、網絡協議
- 網絡協議
- http
- 構成:起始行(GET =>200),首部頭 (ACCEPT=>CONTENT-TYPE),主體 name =》tongbo
- 版本:
- 1.0
- 1.1
- 2.0 :多路復用、流量控制
- 長連接
- 在一個連接上發送多個數據包
- 心跳、如何發送心跳
- httpdns
- 定義:用http協議代替原始的udp dns協議,可以繞過運營商的local dns
- 解決問題:避免local dns造成的域名劫持問題和調度不精確問題(更多是在移動客戶端)
- 其他解決方案
- 客戶端dns緩存
- 熱點域名解析
- 懶更新策略(ttl過期后再同步)
- post請求分割head 和body
- get vs post:
- get(
- 安全冪等,請求實體資源
- 參數只能url編碼,且參數長度有限制
- 瀏覽器會自動加cache
- post
- 附加請求實體于服務器
- 產生兩個tcp數據包
- 數據支持多種編碼格式
- resultful
- get:獲取資源
- post:新建資源
- put:更新完整資源
- delete:刪除資源
- patch:更新部分資源
- Rpc VS Http/rest
- http/rest
- 同步阻塞
- 異步回調
- 優點
- 客戶端支持度高
- 監控方便
- 注意點
- 通信效率低
- rest的put/delete支持度差
- rpc
- 分類
- soap(http)
- protocol buffer(tcp)
- thrift(tcp)
- 優勢
- 二進制支持
- 自動生成服務端、客戶端代碼,支持語言豐富
- 自帶序列化
- 注意點
- 字段類型與定義問題
- tcp
- 面向連接,先建立(握手),然后釋放(揮手確認拜拜)
- 只能點對點
- 可靠交付(相對來說),全雙工,接收和發送端都設有發送和接收cache
- 面向字節流(流:一連串,無結構的的信息流,流入到進程或從進程流出的字節序列,而一個報文段多少字節是根據窗口值和網絡擁塞程度動態變化的)
- 釋放:
- 客戶端:FIN_WAIT 1,停止發送數據給服務端。等待服務端確認
- 服務端:ack ,進入CLOSE_WAIT(關閉等待),此時如果服務端有數據要發送,客戶端還可以接收。
- 客戶端收到服務端確認后,進入FIN_WAIT 2,等待服務器發出連接釋放報文段。
- 此時如果服務端沒有數據要發送,發送上步驟客戶端等待的釋放報文段,然后服務端進入LAST_ACK
- 客戶端收到服務端的last_ack后,發出確認,進入TIME_WAIT,經過2MSL后,客戶端關閉
- 服務端收到客戶端報文段后,進入CLOSE

- 關于TIME_WAIT:
- time_wait是一種TCP狀態,等待2msl可以保證客戶端最后一個報文段能夠到達服務器,如果未到達,服務器則會超時重傳連接釋放報文段。使得客戶端、服務器都可以正常進入到CLOSE狀態。
- 關于粘包
- 分包:在一個消息體或一幀數據時,通過一定的處理,讓接收方能從字節流中識別并截取(還原)出一個個消息體。
- 短連接tcp分包:發送方關閉連接,接收方read 0,就知道消息尾了
- 長連接TCP分包:
- 消息長度固定or消息頭中加長度字段
- 固定消息邊界,比如http:rn
- 利用消息本身格式,如xml,json
- 特性協議
- 停等
- 超時重傳
- 慢啟動
- 滑動窗口
- 快速重傳
- udp
- 無連接、best effort、面向報文(不合并、不拆分,保留邊界)
- 無擁塞控制、流量控制、首部開銷小(8個字節,而tcp有20個首部)
- 支持一對一,一對多,多對一
- 自定義協議
- rpc
九、大前端
- js
- 百度統計的實現
- 基于cookie,引入js腳本及baidu個人賬戶id,讀取當前信息,適當節點發送請求給百度服務器
十、中間件
- 中間件
十一、php框架
- php框架
- ci
- yii
- laravel
- AppServiceProvider register:服務提供者注冊
- iocContainer:(工廠模式的升華:ioc容器)
- 控制反轉(inversion of control)可以降低計算機代碼之間的耦合,其中最常見的方式叫做依賴注入。(Dependence Injection),還有一種方式為依賴查找。
- 實現方式
- 基于接口:實現特定接口以供外部容器注入所依賴類型的對象。
- 基于set方法:還沒搞明白。
- 基于構造函數:實現特定參數的構造函數
- 管理類依賴
- 執行(依賴注入DI):通過構造函數或者某些情況下通過setter方法將類依賴注入到類中,容器并不需要被告知如何構建對象,因為他會使用php的反射服務自動解析出具體的對象。
- swoole
- 依賴注入與控制翻轉
十二 、運維
- 運維&架構
- 服務器cpu99%如何分析
- mysql 占cpu如何分析
- php占cpu較高如何分析
- sso實現方法
- mysql優化方法
- 如何提高監測數據的準確性
- docker 原理及引用及編排管理
十三、golang
- golang
十四、 Linux
- linux
- epoll
- 查看負載:cat /proc/loadavg || w || top
- df
- top shift M
- free
- ipstat
- strace
- grep [-A ,-B, -C]HTTP/1.1" 200 access.log |wc -l
- socket和管道(pipe)的區別:socket全雙工,pipe半雙工*2
- awk
- awk {print $1} access.log |sort |uniq |wc -l
十五、nginx
- nginx
- worker_connections
- upstream weight
- 負責均衡實現方式
- 輪詢
- ip 哈希
- 指定權重
- 第三方
- fair
- url_hash
十六、分布式 | 微服務
- 分布式
- redis 分布式鎖問題
- cap 及常見應用關注cap哪兩點
- 微服務
- 最佳原則
- 高內聚:修改一個功能,只需要改一個服務
- 低耦合:修改了一個地方,不需要改其他的地方(下游消費者不受影響)
- 業務內原則:
- 新服務用新的微服務,確定無誤后保留推進,否則調整
- 老的保留,直到新服務穩定再切換
- 必需的的監控與日志|生產-訂閱—消費模型
- 嘗試對外不可見的服務先做試點,錯誤郵件、日志、系統內調用、api內部分成熟接口
- 考慮問題
- 服務發現是否需要客戶端自實現?
- 服務可用性保證
- 要不要拆MySQL表?保證服務底層的高內聚?異或是存到nosql
- 數據一致性問題?主從|緩存
- 服務監控日志存儲及查詢功能是否需要自實現?
- 基于事件 生產|消費模型選型
- rabbitmq
- kafka
- redis 隊列
- 請求失敗是否需要存入隊列以便再次發起(最大重試次數與死信隊列)?
其他
- 其他
- 兩個絕對路徑,求之間的相對路徑
- 分布式
- 基礎
- cap原理
- 解決多個節點數據一致性的方案其實就是共識算法
- 分布式協議
- Paxos:Proposer, Acceptor, Learner
- ZAB:Follower, Leader, Observer
- raft:leader ,follower,candidate

- 分布式工具
- zk:zab(base paxos)protocol,
- etcd:raft protocol(mini PAXOS),k-v database
具體
- 如何對一個大文件排序(裝不進內存的)-好未來
- 思路:
- map reduce
- 分割成小文件(臨時文件)
- 去重
- awk grep end for sort
- 輸入輸出緩沖區
- 快速排序代碼
- 冒泡排序代碼
- 外層循環 0到n-1 //控制比較輪數 n 表示元素的個數
- 內層循環 0到n-i-1 //控制每一輪比較次數
- 兩兩比較做交換
- 外層循環開始聲明 is_switch flag為false,內層循環有交換為true,外層循環結束時判斷無switch break
- 歸并排序代碼
,