PHP高級工程師面試題

準備

  1. 自我介紹:說上家公司負責的項目或者濃縮簡歷。
  2. 簡歷項目經驗層次php

    • 利用什麼技術
    • 實現了什麼功能
    • 遇到什麼問題
    • 達到類什麼結果
  3. 指望薪資
  4. 應用型的問題:要記得站高看遠、架構分層
  5. 涉及管理經驗及自身對相項目管理的理解

知識點列表

1、Redis

  1. redishtml

    • 應用場景前端

      • string
      • hash
      • set:去重
      • zset: 排行榜
      • list:(阻塞隊列、消息通訊)
      • HyperLogLog:大量統計(非精確)
    • 內部數據結構node

      • dict:key[string] VS value (redis obj);拉鍊法解決衝突(同php);裝載因子(哈希表已保存節點數量 / 哈希表大小)超過預約值自動擴充內, 引起(增量式)rehashingmysql

        • 根據ht[0]建立一個比原來size大一倍(也可能減小)的hashtable,
        • 從新計算hash和index值,根據rehashindex逐步操做
        • 到達必定閾值(ht[0]爲空)操做中止
        • 期間響應客戶端react

          • 寫操做:寫到新的ht[1]
          • 讀操做:先讀ht[0],再讀ht[1]
      • sds:simple dynamic stringlinux

        • string的底層實現爲sds,可是string存儲數字的時候,執行incr decr的時候,內部存儲就不是sds了。
        • 二進制安全binary safe(5種類型的header+falgs獲得具體類型,進而匹配len和alloc)
      • robj:redis object,爲多種數據類型提供一種統一的表示方式,同時容許同一類型的數據採用不一樣的內部表示,支持對象共享和引用計數。nginx

        • 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_laravel

      • stringgolang

        • 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等是原子的
      • 事務是保證批量操做的原子性
    • 主從複製過程:

      1. 從服務器向主服務器發送sync
      2. 主服務器收到sync命令執行BGSAVE,且在這期間新執行的命令保存到一個緩衝區
      3. 主執行(BGSAVE)完畢後,將.rdb文件發送給從服務器,從服務器將文件載入內存
      4. 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隊列特殊關注(可能坑)之處

      1. 隊列可能丟東西

        • 好比redis掛了,producer沒有中止,可是隊列數據沒法寫入(除非同步落地到mysql)
      2. 隊列的consumer 須要手動處理commit協議

        • 若是consumer處理完,表示真正完成
        • 若是沒有處理完?放回隊列?直接丟棄?
      3. 事件重放機制不支持

        • 好比consumer消費錯了,那能不能將隊列回放呢再次處理呢?
      4. 隊列最大長度及過時時間

        • 若是producer遠大於consumer,撐爆了怎麼辦
        • 若是comsumer 一直沒有處理,producer的數據如何處理
      5. exactly once
      6. 單機鎖sennx或者基於set衆多參數沒問題,集羣下可利用tag機制
      7. 如何保證業務執行時間超過鎖的過時時間,而引發誤刪除操做。答案是能夠加一個惟一標識
    • 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到一個節點?用{}

2、MySql

  1. 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
      • 區別:

        1. myisam採用非彙集索引,innodb採用彙集索引
        2. myisam索引myi與數據myd文件分離,索引文件僅保存數據記錄指針地址。
        3. myisam的主索引與輔助索引在結構上沒區別,而innodb不同:innodb的全部輔助索引都引用主索引做爲data域。
        4. innodb支持事務,行級鎖。myisam不行。
        5. innodb必須有主鍵,而myisam能夠沒有。
      • 相同點:

        • 都是b+tree 索引
    • 存儲

      • innodb

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

          • 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之間
    • 隔離級別

      • 事務的隔離性是數據庫處理數據的基礎之一,隔離級別是提供給用戶在性能和可靠性作除選擇和權衡的配置項目,如下四種狀況都有一個前提(在同一個事務中
      • 1.read_uncommited:髒讀,未提交讀。不加任何鎖,能讀取到其餘會話中未提交事務修改的數據,主流數據庫幾乎沒有這麼用。的見下圖
      • clipboard.png
      • 2.read_commit:RC,不可重複讀,已提交讀。注意這個與1的區別是,讀取不加鎖,可是數據的寫入、修改和刪除是須要加鎖的,而1是啥鎖都不加。啥🔒都不加。只對記錄加記錄鎖,而不會在記錄間加間隙鎖。因此容許新的記錄插入到被鎖定記錄的附近,因此屢次使用查詢語句時,可能獲得不一樣的結果,non_repeatable_read,見下圖,第二個事務修改了id=1的數據後,第一個事務再次讀取的時候結果不同。這就是不可重複讀,即兩次結果不同。
      • image.png
      • 3.repeatable_read【默認級別】:RR,可重讀,幻讀,返回第一次的查詢的快照(不會返回不一樣數據)。雖然事務2提交了更改,可是事務1仍然讀到的是事務2未修改的狀態。見下圖
      • image.png
      • 4.serialize:解決了幻讀,可串行化。幻讀和可重複度讀的區別在於致使幻讀的是其餘事務的insert。這樣會引發第一個事務莫名其妙的多出來一條數據。幻讀主要是依靠讀鎖寫鎖相互獨立(互斥),可是會極大的下降併發能力。
    • 索引機制(算法)

      • hash
      • b+tree(m階b+tree)

        • 全部數據保存在葉子節點,有k個子樹的中間節點包含有k個元素
        • 全部葉子節點包含了所有的元素信息,及指向這些元素記錄的指針,且葉子節點自己依關鍵字的大小自小而大順序連接
        • 全部的中間節點元素都同時存在於子節點,在子節點元素中都是最大(或最小)元素(或者說:每個父節點的元素都出如今子節點中,是子節點的最大或者最小元素)
        • 插入的元素,要始終保持最大元素在根節點中,再次說:全部的葉子節點包含了全量元素信息。每一個葉子節點都帶有指向下個節點的指針,造成了有序鏈表
        • clipboard.png
    • 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-區別

      1. b+中間節點沒有衛星數據,而b-tree有衛星數據(能夠理解爲key+data的二維數組),因此前者一樣大小能夠容納更多的節點元素。這樣又致使了b+比b更「矮胖」,更進一步減小了io查詢次數。很好的解釋了下面這句話:在cluster index(彙集索引中),葉子節點直接包含衛星數據;在非彙集索引中nonclustered index中,葉子節點帶有指向衛星數據的指針。
      2. b-只要查找到匹配元素,直接返回,網絡匹配元素處理中間節點仍是葉子節點。而b+查詢必須查找到葉子節,相對於b-,b+無需返回上層節點重複遍歷查找工做,因此得出b-查找並不穩定,而b+是穩定的,b+樹經過雙向鏈表將葉子節點串聯起來,基於空間換時間。目的就是支持倒敘和順序查詢。
      3. 針對範圍查詢,b-須要n次中序遍歷,而b+只須要經過子節點鏈表指針遍歷便可。
    • 種類

      • optimistic lock樂觀鎖(並不是真正的鎖,是基於版本號基礎的先嚐試再更改,loop and try)
      • 特色:不會真死鎖,必定條件下有較高的衝突頻率和重試成本,可是相對悲觀能夠有更好的併發量
      • pessimistic lock悲觀鎖

        • 爲了保證事務的隔離性,就須要一致性鎖定讀。讀的時候要加鎖,防止其餘事務再次更改,修改的時候也要加鎖,其餘事務沒法讀取。主要就是依靠數據庫的鎖機制來實現,同時缺點很明顯,就是會帶來性能的開銷,併發的減小。
    • innodb的MVCC(Multi-Version Concurrency Control)

      - 翻譯成中文叫~~心理醫生~~ ,多版本併發控制,適用於行鎖的、事務性的數據庫模型。
      - 適用於innodb的rc和rr級別,由於可串行化涉及到鎖表
      - 實現思想是在每行增長一個create_verison和delete_version字段
      - update 是插入一個新行,先保存當前版本號到舊行的delete_version,且新建行的new_create_version也就是delete_version
      - delete操做就是直接標記delete_version
      - insert的時候,就是保存至create_version
      - selete的時候能夠這樣
          - 讀delete_version爲空的
          - 大於當前事務版本號的
          - 建立版本號<=當前事務版本號的
    • 粒度劃分

      • 行鎖
      • 表鎖
    • 意向鎖 intention lock(表級鎖)

      • 場景:A對錶中一行進行修改,B對整個表修改。若是沒有如下的兩個鎖,B將對全表掃描是否被鎖定。反之,A能夠對某行添加意向互斥鎖(表級),而後再添加互斥鎖(行級),而後B只須要等待意向互斥鎖釋放)
      • 意向共享鎖
      • 意向互斥鎖
    • 共享鎖shard lock 讀鎖(行鎖)
    • 排它鎖exclusive lock 寫鎖(行鎖)
    • 鎖的算法

      • record lock:加到索引記錄上的鎖,若是經過where條件上鎖,而不知道具體哪行,這樣會鎖定整個表
      • gap lock:間隙鎖某個區間的鎖定,對索引記錄中的一段連續區域的鎖。
      • next-key lock:行鎖和GAP(間隙鎖)的合併,next-key鎖是解決RR級別中 幻讀問題的主要方案。能夠搜索關鍵字 快照讀(snapshot read)和當前讀(current read)去了解~
    • 死鎖:
      clipboard.png
    • 注意區分 deadlock VS lock wait timeout
  2. 分庫分表
  3. 主從
  4. ACID
  5. 覆蓋索引(複合索引)

    • 定義:包含兩個或多個屬性列的索引稱爲複合索引。若是查詢字段是普通索引,或者是聯合索引的最左原則字段,查詢結果是聯合索引的字段或者是主鍵。這種就沒必要經過主鍵(彙集索引再次查詢)
    • 目的:減小磁盤io,不用回表
    • b+樹索引
  6. 彙集索引cluster index 通常爲primary key

    • 定義:按照每張表主鍵構建一棵B+TREE,葉子節點放的整張表的行記錄數據
    • 與之相對應的是輔助索引(secondary index)
    • innodb存儲引擎支持覆蓋索引,即從輔助索引中能夠查到查詢記錄,而不須要查詢彙集索引中的記錄。
    • b平衡樹+樹索引
      clipboard.png
    • 上圖對應的表結構:
    • 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+樹
    • 每次給字段建一個索引,字段中的數據就會被複制一份出來。用於生成索引,(考慮磁盤空間)。無論何種方式查表,最終都會利用主鍵經過彙集索引來定位到數據。彙集索引(主鍵)是通往真實數據的惟一出路。
  7. 輔助索引:非彙集索引均可以被稱做輔助索引,其葉子節點不包含行記錄的所有數據,僅包含索引中的全部鍵及一個用於查找對應行記錄的【書籤(即主鍵或者說彙集索引)】,下面兩個圖爲輔助索引(first_name,age)以及經過主鍵再次查找的過程

    • clipboard.png
    • clipboard.png
  8. 聯合索引:與覆蓋索引沒有區別,或者理解爲覆蓋索引是聯合索引的最優解(無需經過主鍵回表)。
  9. 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(粗略統計,不是精確)
  10. 其餘:

    1. varchar爲啥爲65535?compact行記錄的第一個字段爲變長字段長度列表,爲2個字節16位。參考
    2. 一個表最多多少行?1023,具體也是看行格式的數據結構便可,參考上文的參考連接。
    3. 爲何建議給表加主鍵?主鍵的做用是把數據格式轉爲索引(平衡樹)
    4. 聯合索引在b+樹中如何存儲?
    5. 爲何索引不直接用二叉查找樹,要用b樹,b+樹?主要考慮減小磁盤io(考慮磁盤物理原理及局部性與磁盤預讀的特性:)
    6. myisam和innodb必須有主鍵嗎?innodb必須有,數據文件須要按照主鍵彙集,若是沒有innodb會自動生成。

3、算法&數據結構

  • 最小堆:根節點爲最小值,且節點比其餘孩子小
  • 平衡樹(avl 紅黑樹)
  • 最大堆:根節點爲最大值,且節點比其餘孩子大
  • sikplist
  • hash

    • hash 碰撞緣由
    • hash 碰撞解決方案

      • 拉鍊,塞到鏈表裏。優勢是相對簡單,可是須要附加空間(想到了php max_input_vars
      • 開放尋址,優勢是空間利用率高,一直找..

        • 線性探測
        • 二次探測再散列函數
        • 僞隨機數
  • 給定數值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功能?【雙向鏈表】
    • 如何實現瀏覽器前進後退功能?【兩個棧】

4、設計模式

  1. 設計模式

    • 單例模式 (static ,consturct)

      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]
    • 門面模式

      • 對客戶屏蔽子系統組件,減小子系統與客戶之間的鬆耦合關係

5、正則表達式

  1. 正則表達式

    • 應用場景

      • 範匹配
      • 模版引擎
      • 詞法分析器(lex)
    • 常見正則

6、PHP

  1. 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 (顯示關閉,後期使用須要顯示開啓)

7、操做系統

  1. 操做系統

    • 多線程
    • 多進程
    • 協程的理解
    • socket和管道的區別
    • 進程間通訊手段

      • 共享內存
      • rpc
      • 管道
    • 線程間通訊手段

      • 讀寫進程數據段

8、網絡協議

  1. 網絡協議

    • 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
        • clipboard.png
        • 關於TIME_WAIT:

          • time_wait是一種TCP狀態,等待2msl能夠保證客戶端最後一個報文段可以到達服務器,若是未到達,服務器則會超時重傳鏈接釋放報文段。使得客戶端、服務器均可以正常進入到CLOSE狀態。
        • 關於'粘包'

          • 分包:在一個消息體或一幀數據時,經過必定的處理,讓接收方能從字節流中識別並截取(還原)出一個個消息體。
          • 短鏈接tcp分包:發送方關閉鏈接,接收方read 0,就知道消息尾了
          • 長鏈接TCP分包:

            • 消息長度固定or消息頭中加長度字段
            • 固定消息邊界,好比http:rn
            • 利用消息自己格式,如xml,json
      • 特性協議

        • 停等
        • 超時重傳
        • 慢啓動
        • 滑動窗口
        • 快速重傳
    • udp

      • 無鏈接、best effort、面向報文(不合並、不拆分,保留邊界)
      • 無擁塞控制、流量控制、首部開銷小(8個字節,而tcp有20個首部)
      • 支持一對一,一對多,多對一
    • 自定義協議
    • rpc

9、大前端

  1. js

    • 百度統計的實現

      • 基於cookie,引入js腳本及baidu我的帳戶id,讀取當前信息,適當節點發送請求給百度服務器

10、中間件

  1. 中間件

    • rebbitmq
    • kafka
    • Redis 隊列

11、php框架

  1. php框架

    • ci
    • yii
    • laravel

      • AppServiceProvider register:服務提供者註冊
      • IocContainer:(工廠模式的昇華:ioc容器)

        • 控制反轉(inversion of control)能夠下降計算機代碼之間的耦合,其中最多見的方式叫作依賴注入。(Dependence Injection),還有一種方式爲依賴查找。
        • 實現方式

          • 基於接口:實現特定接口以供外部容器注入所依賴類型的對象。
          • 基於set方法:還沒搞明白。
          • 基於構造函數:實現特定參數的構造函數
        • 管理類依賴
        • 執行(依賴注入DI):經過構造函數或者某些狀況下經過setter方法將類依賴注入到類中,容器並不須要被告知如何構建對象,由於他會使用php的反射服務自動解析出具體的對象。
    • swoole
    • 依賴注入與控制翻轉

十二 、運維

  1. 運維&架構

    • 服務器cpu99%如何分析
    • mysql 佔cpu如何分析
    • php佔cpu較高如何分析
    • sso實現方法
    • mysql優化方法
    • 如何提升監測數據的準確性
    • docker 原理及引用及編排管理

十3、golang

  1. golang

    • todo

十4、 Linux

  1. 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

十5、nginx

  1. nginx

    • worker_connections
    • upstream weight
    • 負責均衡實現方式

      • 輪詢
      • ip 哈希
      • 指定權重
      • 第三方

        • fair
        • url_hash

十6、分佈式 | 微服務

  1. 分佈式

  2. 微服務

    • 最佳原則

      • 高內聚:修改一個功能,只須要改一個服務
      • 低耦合:修改了一個地方,不須要改其餘的地方(下游消費者不受影響)
      • 業務內原則:

        • 新服務用新的微服務,肯定無誤後保留推動,不然調整
        • 老的保留,直到新服務穩定再切換
        • 必需的的監控與日誌|生產-訂閱—消費模型
        • 嘗試對外不可見的服務先作試點,錯誤郵件、日誌、系統內調用、api內部分紅熟接口
    • 考慮問題

      • 服務發現是否須要客戶端自實現?
      • 服務可用性保證
      • 要不要拆MySQL表?保證服務底層的高內聚?異或是存到nosql
      • 數據一致性問題?主從|緩存
      • 服務監控日誌存儲及查詢功能是否須要自實現?
      • 基於事件+生產|消費模型選型

        • rabbitmq
        • kafka
        • redis 隊列
      • 請求失敗是否須要存入隊列以便再次發起(最大重試次數與死信隊列)?

其餘

  1. 其餘

    • 兩個絕對路徑,求之間的相對路徑
    • 分佈式

      • 基礎

        • cap原理
        • 解決多個節點數據一致性的方案其實就是共識算法
      • 分佈式協議

        • Paxos:Proposer, Acceptor, Learner
        • ZAB:Follower, Leader, Observer
        • raft:leader ,follower,candidate
        • clipboard.png
      • 分佈式工具

        • zk:zab(base paxos)protocol,
        • etcd:raft protocol(mini PAXOS),k-v database

具體

  1. 如何對一個大文件排序(裝不進內存的)-好將來

    • 思路:

      • map reduce
      • 分割成小文件(臨時文件)
      • 去重
      • awk grep end for sort
      • 輸入輸出緩衝區
  2. 快速排序代碼
  3. 冒泡排序代碼

    • 外層循環 0到n-1 //控制比較輪數 n 表示元素的個數
    • 內層循環 0到n-i-1 //控制每一輪比較次數
    • 兩兩比較作交換
    • 外層循環開始聲明 is_switch flag爲false,內層循環有交換爲true,外層循環結束時判斷無switch break
  4. 歸併排序代碼

面試完成後

  1. 自身定位與公司給定技術評級
  2. todo

其餘參考

  1. [感受php要求好高?](zhihu.com/question/21866412/answer/349627984)
相關文章
相關標籤/搜索