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


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

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

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

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

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

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

- 上圖對應(yīng)的表結(jié)構(gòu):
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)
- 一張表一定包含一個聚集索引構(gòu)成的b 樹以及若干輔助索引構(gòu)成的b 樹
- 每次給字段建一個索引,字段中的數(shù)據(jù)就會被復(fù)制一份出來。用于生成索引,(考慮磁盤空間)。不管何種方式查表,最終都會利用主鍵通過聚集索引來定位到數(shù)據(jù)。聚集索引(主鍵)是通往真實數(shù)據(jù)的唯一出路。
- 輔助索引:非聚集索引都可以被稱作輔助索引,其葉子節(jié)點不包含行記錄的全部數(shù)據(jù),僅包含索引中的所有鍵及一個用于查找對應(yīng)行記錄的【書簽(即主鍵或者說聚集索引)】,下面兩個圖為輔助索引(first_name,age)以及通過主鍵再次查找的過程


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

- 關(guān)于TIME_WAIT:
- time_wait是一種TCP狀態(tài),等待2msl可以保證客戶端最后一個報文段能夠到達服務(wù)器,如果未到達,服務(wù)器則會超時重傳連接釋放報文段。使得客戶端、服務(wù)器都可以正常進入到CLOSE狀態(tài)。
- 關(guān)于粘包
- 分包:在一個消息體或一幀數(shù)據(jù)時,通過一定的處理,讓接收方能從字節(jié)流中識別并截取(還原)出一個個消息體。
- 短連接tcp分包:發(fā)送方關(guān)閉連接,接收方read 0,就知道消息尾了
- 長連接TCP分包:
- 消息長度固定or消息頭中加長度字段
- 固定消息邊界,比如http:rn
- 利用消息本身格式,如xml,json
- 特性協(xié)議
- 停等
- 超時重傳
- 慢啟動
- 滑動窗口
- 快速重傳
- udp
- 無連接、best effort、面向報文(不合并、不拆分,保留邊界)
- 無擁塞控制、流量控制、首部開銷小(8個字節(jié),而tcp有20個首部)
- 支持一對一,一對多,多對一
- 自定義協(xié)議
- rpc
九、大前端
- js
- 百度統(tǒng)計的實現(xiàn)
- 基于cookie,引入js腳本及baidu個人賬戶id,讀取當(dāng)前信息,適當(dāng)節(jié)點發(fā)送請求給百度服務(wù)器
十、中間件
- 中間件
十一、php框架
- php框架
- ci
- yii
- laravel
- AppServiceProvider register:服務(wù)提供者注冊
- iocContainer:(工廠模式的升華:ioc容器)
- 控制反轉(zhuǎn)(inversion of control)可以降低計算機代碼之間的耦合,其中最常見的方式叫做依賴注入。(Dependence Injection),還有一種方式為依賴查找。
- 實現(xiàn)方式
- 基于接口:實現(xiàn)特定接口以供外部容器注入所依賴類型的對象。
- 基于set方法:還沒搞明白。
- 基于構(gòu)造函數(shù):實現(xiàn)特定參數(shù)的構(gòu)造函數(shù)
- 管理類依賴
- 執(zhí)行(依賴注入DI):通過構(gòu)造函數(shù)或者某些情況下通過setter方法將類依賴注入到類中,容器并不需要被告知如何構(gòu)建對象,因為他會使用php的反射服務(wù)自動解析出具體的對象。
- swoole
- 依賴注入與控制翻轉(zhuǎn)
十二 、運維
- 運維&架構(gòu)
- 服務(wù)器cpu99%如何分析
- mysql 占cpu如何分析
- php占cpu較高如何分析
- sso實現(xiàn)方法
- mysql優(yōu)化方法
- 如何提高監(jiān)測數(shù)據(jù)的準確性
- 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)的區(qū)別:socket全雙工,pipe半雙工*2
- awk
- awk {print $1} access.log |sort |uniq |wc -l
十五、nginx
- nginx
- worker_connections
- upstream weight
- 負責(zé)均衡實現(xiàn)方式
- 輪詢
- ip 哈希
- 指定權(quán)重
- 第三方
- fair
- url_hash
十六、分布式 | 微服務(wù)
- 分布式
- redis 分布式鎖問題
- cap 及常見應(yīng)用關(guān)注cap哪兩點
- 微服務(wù)
- 最佳原則
- 高內(nèi)聚:修改一個功能,只需要改一個服務(wù)
- 低耦合:修改了一個地方,不需要改其他的地方(下游消費者不受影響)
- 業(yè)務(wù)內(nèi)原則:
- 新服務(wù)用新的微服務(wù),確定無誤后保留推進,否則調(diào)整
- 老的保留,直到新服務(wù)穩(wěn)定再切換
- 必需的的監(jiān)控與日志|生產(chǎn)-訂閱—消費模型
- 嘗試對外不可見的服務(wù)先做試點,錯誤郵件、日志、系統(tǒng)內(nèi)調(diào)用、api內(nèi)部分成熟接口
- 考慮問題
- 服務(wù)發(fā)現(xiàn)是否需要客戶端自實現(xiàn)?
- 服務(wù)可用性保證
- 要不要拆MySQL表?保證服務(wù)底層的高內(nèi)聚?異或是存到nosql
- 數(shù)據(jù)一致性問題?主從|緩存
- 服務(wù)監(jiān)控日志存儲及查詢功能是否需要自實現(xiàn)?
- 基于事件 生產(chǎn)|消費模型選型
- rabbitmq
- kafka
- redis 隊列
- 請求失敗是否需要存入隊列以便再次發(fā)起(最大重試次數(shù)與死信隊列)?
其他
- 其他
- 兩個絕對路徑,求之間的相對路徑
- 分布式
- 基礎(chǔ)
- cap原理
- 解決多個節(jié)點數(shù)據(jù)一致性的方案其實就是共識算法
- 分布式協(xié)議
- 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
具體
- 如何對一個大文件排序(裝不進內(nèi)存的)-好未來
- 思路:
- map reduce
- 分割成小文件(臨時文件)
- 去重
- awk grep end for sort
- 輸入輸出緩沖區(qū)
- 快速排序代碼
- 冒泡排序代碼
- 外層循環(huán) 0到n-1 //控制比較輪數(shù) n 表示元素的個數(shù)
- 內(nèi)層循環(huán) 0到n-i-1 //控制每一輪比較次數(shù)
- 兩兩比較做交換
- 外層循環(huán)開始聲明 is_switch flag為false,內(nèi)層循環(huán)有交換為true,外層循環(huán)結(jié)束時判斷無switch break
- 歸并排序代碼
,