面霸的八月:小米麵試記

來源:互聯網
上載者:User
原文出處:  香草的技術部落格(@平凡的香草)    

書接上回,今天敘述小米的面試經曆。這裡可能有一些技術理解和技術方案,歡迎討論。另昨天共計收入7筆共95元,夠我喝幾杯咖啡了,謝謝所有捐錢的朋友。

  小米:營運部

在小米是聊了兩個部門的,首先是營運部門,在 @wilbur井源 的熱情招待下,吃了頓大餐,抱歉的是我沒有帶足現金,所以付款時我無法“客氣”,改天補請。

wilbur井源同兩位同事與我四人邊吃邊聊,我簡單介紹當前的網站的服務結構以及部分業務的技術設計,比如網站架構的分布情況,Distributed File SystemfastDFS的使用狀況、Redis和MySQL的一些部署結構和技術,其中尤其對監控這件事情我做了詳細一些的說明(詳見服務可用性監控的一些思考以及實踐),中間提到了關於主動式監控(主動式監控是指通過營運和業務部門指定監控的系統資源、介面、頁面、日誌等,主動發現問題,警報層級較高)、被控監控的概念(指通過JSlib或用戶端lib對於所有的操作尤其是網路介面的請求進行監控,對異常進行彙報,通過收集日誌的方式進行可用性問題的發現)。當然,還有必不可少的是對haproxy的運行和最佳化狀況(參見Haproxy配置),MySQL的架構及最佳化方式(見MySQL架構及營運),Redis常見的效能問題(參見redis架構及營運問題),fastDFS同其他分布式儲存MogileFS、TFS、lusterfs的在功能、營運成本上的橫向比較,多IDC圖片cache的部署以及效能最佳化(參見多idc圖片Cache部署),Linux核心參數(參見Linux核心配置)和讓我特別自豪的是關於網卡smp affinity/RPF/RFS的最佳化效果(參考3/4/5)的一些最佳化等。當然,這是正經的營運部門,我闡述了我對“營運”工作的理解:60%的分析整理工作加上40%的技能,分析整理能力是做好營運的基礎。

井源也詢問了幾個安全問題,我粗淺的理解是:從系統管理員(SA)的經曆來講,做好IT系統規劃,合理區分伺服器角色,通過iptables是能夠阻止大多數接入層非法請求的;對於web業務的安全來講,SQL注入、CRSF等攻擊是因為對輸入輸入內容的過濾不嚴格導致的,在開發的過程中合理使用一些優秀架構或lib,也能夠避免大多數漏洞的產生;有個比較有意思的話題是關於溢出的,現在我已經不會計算溢出地址了,在我當script boy的時候研究過一點,忘光光了,慚愧……

井源這邊的效率很好,邊吃邊聊的氣氛很放鬆,不過很多問題都停留在一些思路和效果資料上,沒有勾勾畫畫的太多深入的探討。

  電商部

大約8點半左右到的電商部門,常規面試的第一輪都是技術,包括細節。面試官是位張姓的team leader。

在這輪面試的過程中,因為是在會議室,有筆有板,所以我邊講邊寫。大體上介紹了我對web服務架構的理解,我認為,web服務架構大體上離不開這樣幾個層面:接入層(負載平衡)、商務服務層、資料層,一般還會有不少的後台輔助程式進行同步、非同步處理各種不適合在業務層融合的服務單元。資料層可以包括DB、Cache、File等,資料層還可能會有很多中介軟體或Proxy 伺服器用來做資料層的負載平衡或是HA,以及Sharding等。同面試官詳細介紹了當前服務的公司在每一層所採用的技術,分別是:haproxy、nginx+php、twemproxy+redis、MySQL+RedisCache、Varnish+Squid+nginx+fastDFS。

haproxy的伺服器配置是按照100w並發的目標進行配置和最佳化的,計劃100w用戶端串連,考慮每個用戶端串連可能產生1個內部串連,按照每個串連消耗4k(此處修正為17K,haproxy的官方資料,見參考8,感謝 @GNUer 的修正)記憶體來算,大約8G(此處修正為32G)記憶體【這裡的計算還需要再考慮,我擔心haproxy的每個串連消耗17k記憶體是包含對內部伺服器的串連】,實際上往往比這個數字要大。目前達到的最大串連數目測到過16w,在接入層的系統最佳化上分別有:網卡中斷最佳化(參考3/4/5),linux 核心參數最佳化(見linux sysctl.conf配置)。

值得一提的是,我們的haproxy伺服器都是64G記憶體,實際上遠遠永不到這麼多,圖片服務的最外層cache,即Varnish,我們也是部署在haproxy伺服器上的。

在最外層伺服器上,我們每天大約5億+(1-1.5億+的動態請求、3-4億+的圖片請求)的請求量,共計使用7台64G的Dell R410,目前看負載還很低,從系統的各種資源上看,請求量翻倍應該是沒有問題的。

在最外層的伺服器配置上,有一個問題值得注意,即sysctl.conf的配置中,timestamp必須為0,這個在tcp協議的擴充標準中有提到,否有nat環境的用戶端串連有可能產生異常,異常的狀況可以在netstat -s 的輸出中看到。還需要注意的是timestamp=0的情況下,tw_reuse是不生效的。

要保證伺服器能夠接收大並發的串連請求是件不難的事情,但需要考慮一個細節,每接收一個請求,haproxy就需要至少分配一個系統的tcp連接埠請求後面的商務服務器、cache伺服器,系統一個ip地址可用的連接埠數最多為65535,一般還需要減去1024。值得考慮的是減小 tw_bucket 的容量,讓系統在tw_bucket滿的狀況下,對tw狀態的串連進行丟棄,以達到快速回收的目的,tw的預設回收時間的2倍的MSL。還有一個方式就是多配置幾個ip。

還有一個問題,接入層的伺服器往往會開啟iptables,核心中nf的相關配置也是需要最佳化的,比如 nf_conntrack_max、nf_conntrack_tcp_timeout_established等。

在業務層的最佳化有nginx+php(fastcgi串連方式、php-fpm.conf配置中的最佳化),我的一個經驗是,如果nginx同phpcgi運行在同一台伺服器,採用unix socket的方式進行fastcgi協議的互動是效果最快的,比127.0.0.1的迴環地址要快太多。我在08年最佳化過一台伺服器(Dell 2960,16G記憶體),通過兩個步驟,將一台伺服器從900qps,最佳化到6000qps以上,其一是將fastcgi協議運行在unix socket上,其二是合理配置spawn-fcgi的進程數量。現在基本上phpcgi都是運行在php-fpm中的了,其進程池邏輯是我最讚賞的功能之一。

如果nginx和php-fpm不在同一台伺服器上,可以考慮使用fastcgi_keepalive的配置,實現nginx同fastcgi伺服器持久串連,以提高效率。

nginx+php-fpm提供的運行狀態非常有意義,nginx的status模組和php-fpm的status輸出可以告訴我們nginx進程的請求處理狀況,php-fpm的status輸出可以告訴我們php-fpm的進程池設定是否合理。我們目前對這兩個資料通過nagios定期採集,並繪製成圖表,很有“觀賞價值”。

php-fpm.conf的配置中還有幾個參數對最佳化比較重要,其一是進程自動重啟的條件pm.max_requests,其二是php-slow log的配置,slow log 是最佳化php代碼的非常重要的資訊。在我目前的環境中,php的慢執行日誌是通過rsyslog進行傳輸並集中分析的,以此反向推進開發對php代碼的最佳化。

php的伺服器在高並發的情況下,有可能因為伺服器本身可提供的連接埠數量的限制,無法同redis伺服器建立大量的串連,這時候可以在sysctl.conf中配合timestamps=1 加上tw_reuse/tw_recycle的方式,進行連接埠快速回收,以便更好的向資料層建立串連,接入層的haproxy是不可以這樣的。

這一層還涉及到一個安全問題,就是php代碼被修改並掛馬的狀況,我的解決方案是,將php-fpm的運行使用者同php代碼的屬主設定成不同的使用者,並且保證php-fpm的運行使用者不能對php代碼具有寫的許可權。

資料層的情況裡,MySQL主從結構以及MHA+keepalived的高可用配置,這個基本上是看文檔應該就能夠理解的。如果是5.6的新版MySQL,其高可用監控可能可以做的更簡單,MySQL官方提供對應的工具,只是我還沒有測試。對MHA的監控功能,我覺得亮點是MHA對切換過程中MySQL binlog的擷取和執行,在最大程度上避免了資料丟失。但是其缺點也是有的,比如:監控進程在觸發切換後就停止了,一旦觸發,必須重新啟動進程再繼續監控。06年時我在sina做過一個叫Trust DMM的項目,通過 DNS、MON加上自己寫的外掛程式,監控MySQL主從叢集的可用性,可以實現,主庫、主備自動切換(缺乏binlog處理的環節);從庫是一組伺服器,如果從庫發生問題,可以自動下線。只是這套系統部署起來比較麻煩。這個項目曾經獲得過sina的創新一等獎。

我還提到了我認為的DBA日常的工作至少應該包括:審查並執行上線SQL;定期檢查MySQL慢日誌並分析,將分析結果反饋到開發部門進行調整;定期審查資料庫中索引的效率以及可用性,進行最佳化我反饋。現在做一個一般水平的DBA已經相當容易了,對percona的工具瞭解透徹,已經能夠解決非常多的資料庫問題了。

MySQL還有一個難纏的問題,numa架構下,大記憶體伺服器記憶體使用量效率的問題,numactl對策略進行調整,如果使用percona的MySQL版本,可以通過 memlock配置對MySQL的Innodb引擎進行限制,禁止其使用swap。

MySQL常見的架構裡,還有一種主從儲存引擎不一致的方式,即主庫採用Innodb引擎,提高並發寫入的能力,從庫採用Myisam引擎,這種方式目前我們也在採用。這樣做一是為了擷取更好的讀效能,另外是,Myisam引擎的是可以節省記憶體的。Myisam在索引資料記憶體讀取,資料內容磁碟讀取的狀態下,已經可以比較高效的運行了,myisam_use_mmap的配置項,會讓MySQL將myisam的data檔案也mmap到記憶體中,這樣做既高效,又可以使用mysiam引擎的特性。

資料庫主庫要避免一件事情發生,就是無條件刪除和無條件修改,如“delete from table”以及”update table set xxx=yyyy”等無where條件陳述式,原則來講是應該禁止執行的,這樣的許可權不應該開放給開發的同學,甚至DBA都不能無限制的操作。目前我的解決方案是 sql_safe_updates=1,但這配置是不能夠寫my.cnf中的,只能啟動mysql後進入console進行配置。

當前我們還使用了Redis作為DB,基於主從架構,跨IDC。目前的問題是,複製串連斷開後,Redis快照重傳的問題,從庫會在快照替換期間有短暫的效能抖動。 Redis2.8新版本psync的特性應該可以改善這個問題。我們還使用twemproxy,目前部署在每一台php伺服器上,並監聽unix socket,php使用phpredis的模組進行串連。有效減少三向交握的時間。temwproxy還有很多其他的優秀特性,通過一致性hash做cache叢集,可以有效避免cache遷移問題。通過其對後端redis的健康監控,可以自動下線有故障的redis。

還有針對多IDC的圖片儲存和Cache部署情況。目前我們自建的圖片CDN承載網站每天約4億的請求,頻寬最高峰值約1.5G左右,其結構大體上是中心IDC儲存圖片原圖+SQUID disk cache儲存圖片縮圖,在外地IDC使用兩級緩衝,分別為一層SQUID disk cache(兩台,做HA),另一層為Varnish cache(最多四台),實際上,如果僅考慮work around的狀態,squid cache層基本上也可以不要的。但是,目前這樣的結構可以減少varnish回中心節點的請求,減少中心機房頻寬的壓力。這個結構還算簡單,varnish在高並發請求下,有一些資源配置是需要注意的,比如NFILES / VARNISH_MAX_THREADS / nuke_limit 等。

溝通的技術問題還是非常多的,包括在井源那裡提到監控架構的事情,也尤其提到了我對rsyslog的最佳化,最佳化後的rsyslog在可靠性方面是非常值得稱讚的(最佳化思路見參考6)

我有一些將電商三面的營運營運同學的問題綜合到這裡了,有些話重複的就不再描述。

值得一提的是二面是另一位開發負責人,一看就是個很有獨立思考能力的同學,他問了我一個很有意思的問題,大體的意思是,在系統架構方面,有這樣的幾個層次,從下往上:使用開源、精通開源,最佳化並修改開源軟體,創造開源軟體。問我自己評價我是在哪一個層次的。我認真的思考了一下,我應該是在第二個層次,有些精通的,有些修改過的。

電商四面是時間最長的,至少有兩個小時以上,結束的時候已經是夜裡一點四十了,我覺得電商的老大是應該在支付寶裡面給我捐一些錢才好的 ,不知道有沒有小米的同學能夠轉告哈  。我們應該是談到了非常多的事情,包括秒殺的解決方案,包括對持續整合和自動化測試的理解、對後台資料業務類型的開發中資料計算錯誤的理解,時不時能夠得到“我們想的很一致”這樣的評價。

那時已近半夜,記憶進入低效態,一些太瑣碎的事情記不得了,重複的技術方案也不再贅述。下面簡單描述一下我對秒殺的解決方案的理解:10w的資料,從0到10w,不能多賣。目前的問題是,每次到秒殺時分可能同時進入100w的請求/串連。如何破。

我的方案是:排除user、session等外部依賴服務的前提下,兩台ha外面抗並發串連(後來想這個無所謂的,不如做成php的伺服器),三台PHP伺服器(不要使用任何架構,最樸素的純粹PHP代碼),兩台Redis(最初說了一台)。具體最佳化狀況如下: haproxy最佳化能夠支援百萬並發串連,這個很容易了 nginx最佳化worker connections,最佳化nginx的並發支援能力和請求隊列的接收能力 php-fpm最佳化listen.backlog,最佳化fastcgi請求隊列的接收能力。 Redis 假如在秒殺的1分鐘內,伺服器不出現故障,最佳化redis的最大串連數 最佳化所有伺服器的網卡、sysctl參數

php的邏輯可以簡單的理解為對redis的某一個key進行incr原子操作,如果返回的當前數值小於等於10w(兩台redis的情況下應小於等於5w),則認為中籤。

從我以前看到的資料來講,redis的最好狀態在8w qps。nginx+php在08年時已經最佳化到6000 qps,目前的伺服器裝置(雙核16cpu+64G記憶體)達到2、3wQps應該也是不難的事情(這個的最新資料我不知道)。上述配置至少應該能夠在5s內完成10w次redis的incr操作。加上系統各系統對請求隊列的支援,可以幾乎做到不報錯,短暫延遲。

如果考慮1台redis請求量會很高,可以考慮分區,每台分5w。

當然,這是在僅僅思考不到1分鐘內給出的方案,從現在來看,haproxy是可以不要,nginx扛並發串連的能力也不錯。所有的細節還需要通過壓力測試進行驗證。而實際情況加上對其他服務的依賴(我不知到還有哪些,抽絲剝繭去除幹擾),方案也會更加複雜一些。據電商老大講,實際情況是,秒殺的服務用了十幾台伺服器,秒殺的時候偶爾出現一些故障,小米做秒殺的同學,壓力很大哦。

如果你提到要記錄中籤的使用者的uid和中籤號碼,還是redis吧。

(突然wps的linux版崩潰了,只能恢複到這裡,後面的部分內容是重寫的,可能有點混亂)

針對剛才的問題,我在白板上畫了個簡單的架構圖:haproxy+nginx/php+redis,haproxy和nginx/php都是可線性擴充的,redis可以通過sharding來實現擴充。理論上講,一個可擴充的架構是可以滿足任何效能要求的,更何況如此簡單的邏輯,單機效能已經可以做到非常高了。

電商王姓負責人在問我方案時問這個需求會有哪些痛點。我看著白板笑笑:目前看,應該不存在痛點。如果有問題,應該看日誌和服務狀態以及伺服器狀態。

第四面聊得很頭機,對方几次想結束時都突然冒出來一個問題,每一個都會討論比較久,比如背景一些計算操作是否換成java更合適,因為java可以更嚴謹。我說這可能不是語言的問題,而是程式員習慣和素質的問題,如果想換,其實我倒是更願意嘗鮮,比如用go,還可能可以同時滿足效能的問題。

還有突然聊到持續整合,我坦言,我對持續整合的理解停留在用工具實現自動化的測試和發布這樣的層面上,沒有實操經驗。但我個人的一個粗淺的認知是:持續整合的前提是自動化測試,自動化測試的兩個痛點:1,自動化測試案例的設計;2,程式員對自動化測試的理解和心理反抗程度。我在目前單位有過短暫的嘗試:專業的傳統測試人員對測試案例進行設計,程式員接收到的需求應該包括正向邏輯的產品需求和測試案例的需求。開發工作完成的標記是:自己寫的測試案例在自己的代碼上完全通過,代表自己一項開發工作的完成。

說到這裡,對方不禁雙手伸出拇指。(哈哈哈哈)

或多或少也還有一些別的話題,我自認為那晚像演講一樣很精彩,只不過時間已過午夜,其他的一些細節不太記得了,如果想起或小米參加面試的同學有提起,我再補充了。

整場小米的面試兩個部門加起來共計約7個小時,這是我經曆過的最長時間的面試了……小米的面試很辛苦,今天碼字也很辛苦,現在已經是淩晨1點半了,如果你覺得上面的經過對你有所協助或是有意思,就捧個錢場或人場吧: http://me.alipay.com/chunshengster

  參考: Profiling: From single systems to data centers googleusercontent X-Trace: A Pervasive Network Tracing Framework trace-pervasive-network-tracing-framework http://blog.chunshengster.me/2013/05/smp_irq_affinity.html http://weibo.com/1412805292/zvNrDsqtT http://weibo.com/2173311714/zw40tv3D2 http://blog.chunshengster.me/2013/07/high_performance_rsyslogd.html http://www.wandoujia.com/blog/from-qa-to-ep http://cbonte.github.io/haproxy-dconv/configuration-1.5.html#4-maxconn

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.