工具
最后更新于:2022-04-01 06:10:41
# 參考工具
### JavaScript
- [jsPerf — JavaScript performance playground](http://jsperf.com/)
### Database
### 連線池
- [Database Connection Pool Library | Libzdb](http://www.tildeslash.com/libzdb/#)
文章
最后更新于:2022-04-01 06:10:38
# 參考文章
### 概念
- [一步步構建大型網站架構- 架構設計- | 九街| 白開水的博客](http://www.9streets.cn/art-php-489.html)
- [10+個高流量網站架構的效能提升解決方案](http://www.qa-knowhow.com/?p=2314)
### 資料庫
### 連線池
- [Connection pool - Wikipedia, the free encyclopedia](http://en.wikipedia.org/wiki/Connection_pool)
### MySQL
- [KeJyun學習日誌: 在MySQL中MyISAM與InnoDB資料庫引擎比較](http://blog.kejyun.com/2012/12/Compare-MyISAM-And-InnoDB-Database-Engine-In-MySQL.html)
書籍
最后更新于:2022-04-01 06:10:36
# 參考書籍
### MySQL
- [High Performance MySQL, 2nd Edition原文書免費下載](http://it-ebooks.info/book/256/)
參考資料
最后更新于:2022-04-01 06:10:34
# 參考資料
這裏會紀錄一些相關的參考資料,可以去做進一步的學習及查詢
壓力測試
最后更新于:2022-04-01 06:10:32
# 壓力測試
在我們寫完程式並上了伺服器後,若我們的網站需要服務很多人,我們可能會想要這個服務能夠服務多少人,通常我們會對伺服器進行壓力測試。
壓力測試的軟體有很多,我比較常用的是 `Apache AB test` ,簡單的了解伺服器在多少連線下,處理請求(Request)的速度及效能,而同樣的機器在不同的程式處理之下,會有不同的效能,所以沒辦法統一的斷定哪一種機器只能服務多少人,若程式寫的好的話,可能同時可以應付 4、500 人同使請求,但也有程式可能因為效能不佳,僅能服務 4、50 人(伺服器回應時間標準一樣),所以要對自己的應用服務做壓力測試後才知道狀況。
也有很多其他的壓力測試的軟體,只要找出一套適合自己的壓測工具就可以了。
### 參考資料
- [ab - Apache HTTP server benchmarking tool](http://httpd.apache.org/docs/2.2/programs/ab.html)
- [The Will Will Web | 使用 ApacheBench 進行網站的壓力測試](http://blog.miniasp.com/post/2008/06/30/Using-ApacheBench-ab-to-to-Web-stress-test.aspx)
- [Web server benchmarking - Wikipedia, the free encyclopedia](http://en.wikipedia.org/wiki/Web_server_benchmarking)
常見問題
最后更新于:2022-04-01 06:10:29
高可用性的服務架構
最后更新于:2022-04-01 06:10:27
# 高可用性的服務架構
透過不斷的增加 Web Server 就可以提高使用者訪問量,但這樣的架構非常的龐大,當要對這樣的架構進行改動時會相當的不方便,可用性變得不高。
而且部署機器和維護也必變得相當麻煩,龐大的應用服務架構要在 N 台機器上進行複製、啟動都需要花很多的時間,當機器出問題時也很難立即找出拿台機器出了問題,更有可能是某個應用服務的程式出現 Bug,導致整個站掛掉都沒辦法使用了。
在優化調校時也比較難操作,因為部署的機器每一台都需要進襲調校,沒辦法只進行針對性的調校。
餘是為了解決這樣的問題,就發展出大型的分佈式應用,而這樣的架構可能會遇到許多挑戰:
-
分布式應用需要提供高效能且穩定的架構
-
將龐大的應用拆分出來需要耗費很長的時間,而且需要對業務的整理和系統依賴關係進行控制
-
如何維護(依賴管理、執行狀況管理、錯誤追踪、調校優化、監控和示警等)好這個龐大的分佈式應用。
完成這一步後,系統的架構差不多會到相對穩定的階段,也會使用大量便宜的機器去支撐突如其來的訪問流量
# 參考資料
- [一步步構建大型網站架構- 架構設計- | 九街| 白開水的博客](http://www.9streets.cn/art-php-489.html)
Database 讀寫分離
最后更新于:2022-04-01 06:10:25
# Database 讀寫分離
當流量又開始暴增時,會發現原本無限制擴充 Server ($$$)的架構會讓資料庫連線的資源不敷使用。
因為而在做資料異動的時候,若有要更新範圍(range)的資料,很容易把資料進行鎖定,進而彼此影響到查詢上面的效能。在 [80/20 法則](http://wiki.mbalib.com/zh-tw/80/20%E6%B3%95%E5%88%99)中,大部份 80% 人都是在看文章比較多(讀取資料:SELECT),只有少部分 20% 的人或意見領袖,才會發表文章表示看法(異動資料:INSERT、UPDATE、DELETE),而在做資料異動的時候很有可能會對資料進行鎖定,進而去影響讀取的速度。若是要異動範圍(range)的資料,很容易把資料進行鎖定,更會影響到彼此查詢上面的效能。
這時候我們就會想要把資料庫做`讀寫分離`,所以像是 Facebook、部落格之類的媒體,大多會把資料庫做`讀寫分離`,使用者做異動的行為會去主資料庫(Master)去做寫入的動作,然後從資料庫(Slave)在定期的去同步資料庫的內容,而其他大部份的讀者在讀取資料時,都去讀取從資料庫(Slave)的資料,這樣就不會有因為資料異動而導致資料被鎖定,造成讀取變慢的問題。
而在主從架構中,可以是有很多台從的資料庫(Slave),透過分散式處理可以將不同的連線分配給不同的從資料庫(Slave),讓每一台從的資料庫平均分配差不多的連線量,因為需要處理的連線減少了,進而讓每個查詢都能夠在短時間都能夠回應查詢結果,提高系統的可用度。
> 資料庫主從架構中,`主(Master)`資料庫用來做`寫入資料異動(INSERT、UPDATE、DELETE)`的動作,`從(Slave)`資料庫用來做`讀取(SELECT)`的動作。
而若有些很少在查詢的資料,像是 `Log 紀錄`或是在做 `分析的資料`,這類的資料從放在可靠性較高的資料庫(MySQL、Postgres、Oracle...etc)中,對於我們來說是比較浪費的,因為他會佔用存取資料庫的資源,這類的資料我們可能可以考慮用一些 NoSQL 的方案去存取這些資料,讓重要的資料存放在可靠性的資料庫就好,提高資料庫的可用性。
# 參考資料
- [一步步構建大型網站架構- 架構設計- | 九街| 白開水的博客](http://www.9streets.cn/art-php-489.html)
- [80/20 法則](http://wiki.mbalib.com/zh-tw/80/20%E6%B3%95%E5%88%99)
增加更多的 Web Server
最后更新于:2022-04-01 06:10:22
# 增加更多的 Web Server
在做完分散式資料庫及分散式資料表之後,又開始看到流量暴增的的時候,發現系統的回應時間又開始變慢了,你可能會看到 Web Server(Apache、Nginx...etc)那邊阻塞了很多的請求,而導致每個存取的使用者需要時間等待而導致回應時間增加了,這個時候我們就可能需要增加更多的 Web Server 去應付這些大量的請求。
在做完這些工作之後,會進到一個像是可以無限擴充的階段,網站流量增加時,就是不斷的增加 Server ($$$) 去應付大量的流量。
在做 Web Server 負載平衡時可能會遇到下列問題:
- 基本的負載平衡(Apache 負載平衡、LVS...etc)無法應付巨量的請求量
如果經費允許的話(都流量暴增了,會不想要投入更多的 $ 去讓自己的事業擴大嗎 XD),可以採購負載平衡的硬體設備
> e.g. [F5 Load Balancer](https://f5.com/glossary/load-balancer)、[Netsclar Load Balancer](http://www.citrix.com.tw/products/netscaler-application-delivery-controller/overview.html)...etc
若真的經濟不允許,可以將應用從邏輯上做分類,不同類型的應用分散給不同的負載平衡群集處理。
- 訊息同步的文件分享方法出現瓶頸
這時可以根據不同的網站業務需求去做不同的分散式文件系統
### 參考資料
- [一步步構建大型網站架構- 架構設計- | 九街| 白開水的博客](http://www.9streets.cn/art-php-489.html)
- [F5 Load Balancer](https://f5.com/glossary/load-balancer)
- [Netsclar Load Balancer](http://www.citrix.com.tw/products/netscaler-application-delivery-controller/overview.html)
分散式資料
最后更新于:2022-04-01 06:10:20
# 分散式資料
在做資料庫分散之後,若單一資料表的資料太多,我們會想要用分散資料庫的概念,對資料表中的資料進行分散式處理,而會再需要更改程式讀取資料庫及資料表的邏輯架構。
而在這我們就需要規劃資料分散在多個資料庫及資料表的架構,要怎麼去存取,我們通常會設計一個統一的資料庫及資料表資源分散的統一架構,去進行管理資源的存放及存取方式。
像是 Facebook 每天有好幾百萬千萬的文章資訊會被發表出來,我們可能會對各個使用者做文章存取的資源分配,將使用者的資源分配記錄記在統一個資源管理架構中做記錄,紀錄的資訊可能會是 User A 的文章資料存放在 DB_1 及 TABLE_2,而 User B 的文章資料存放在 DB_3 及 TABLE_1,當要存取個別使用者的資料資料,根據資源管理分配的的方式,分別去不同的資料庫及資料表撈取資料。
而當需要使用分散式資料的情況下,可能也會發現因為資料量過大,導致快取同步的方式出了問題,讓快取不能只存放在本地端而用同步的方式進行分享,可能需要採用分散式快取的方式去快取資料。
**_架構圖:_**
![增加 Database Server](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2015-08-11_55c9661c276b3.png)
### 參考資料
- [一步步構建大型網站架構- 架構設計- | 九街| 白開水的博客](http://www.9streets.cn/art-php-489.html)
增加 Database Server
最后更新于:2022-04-01 06:10:18
# 增加 Database Server
在網站成長之後一段時間後,發現資料庫在查詢(SELECT)及資料異動(INSERT、UPDATE、DELETE)之間,因為查詢處理變得太多,使得互相競爭資料庫的資源非常嚴重,進而導致系統回應時間變得很慢。
這時候我們可能會想要把不同的資料表分散在不同的資料庫當中,分散查詢處理的資源,而會需要更改程式讀取資料庫的邏輯架構。
**_架構圖:_**
![增加 Database Server](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2015-08-11_55c9661c19f7e.png)
### 參考資料
- [一步步構建大型網站架構- 架構設計- | 九街| 白開水的博客](http://www.9streets.cn/art-php-489.html)
增加 Web Server
最后更新于:2022-04-01 06:10:16
# 增加 Web Server
隨著網站應用使用者增加,我們會發現 Web Server 機器的壓力變得比較高了,這個時候就會開始考慮增加 Web Server 了。增加 Web Server 除了可以降低機器的壓力外,同時也可以在 Web Server 掛掉後,有備援機器可以使用,避免整個服務完全中斷。
在增加 Web Server 之後,會碰到一些問題:
- 如何將流量平均分配到不同的 Web Server
> 通常我們會使用 Apache 的負載平衡方法,或是 LVS 相關的負載平衡方法去分配這些流量
- 如何讓 Web Server 的資料同步
> 像是使用者的 session 在不同機器要如何同步,可能會考慮使用資料庫、cookie 或同步 Session 的機制
- 快取(cache)資料同步
> 像是快取會員的個人資料,可能會使用快取同步的機制,或者是分散式快取的方式
- 上傳的檔案同步
> 可能會使用檔案共享的方式
**_架構圖:_**
![增加 Web Server](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2015-08-11_55c9661c0dc58.png)
### 參考資料
- [一步步構建大型網站架構- 架構設計- | 九街| 白開水的博客](http://www.9streets.cn/art-php-489.html)
動態資料快取
最后更新于:2022-04-01 06:10:13
# 動態資料快取
`產生的靜態頁面暫存`可以應付整個頁面很少改變的網頁,但是若網頁中有一部分的資料遭到異動,為了讓使用者取得到最新的資料,我們勢必要清除頁面並重新撈取資料庫的資料去產生新的`靜態頁面暫存`。
但對於資料層來說,其實只有`少部分的資料`有異動需要重新讀取,若我們需要重新去資料庫撈取`所有`頁面需要的資料,再去兜頁面所需要的資訊,勢必是浪費資料庫資源的,還記得我在[概念章節](#)中有提到說 `資料庫存取是很昂貴的`,過多的查詢,導致資料庫的存取效率降低,且資料庫的的連線因為系統的限制,所以也沒辦法無限制的增加連線數量。
所以我們會想要把一些很少異動的資料去做快取(Cache)預存下來,當下一位使用者來索取相同的資料時,則不去資料庫進行查詢,直接將之前預存的資料丟回給使用者,提高系統反應的時間及資料存取的效率,快取的資料會依照我們設定資料的過期時間,當超過過期時間後,再重複去資料庫撈取資料,看看有沒有異動。
**_架構圖:_**
![動態資料快取](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2015-08-11_55c9661bde736.png)
### 注意事項
### 快取時間
快取的失效時間通常會依我們的應用去做設定,也因為系統資源的關係(記憶體大小、硬碟容量大小...等等)的原因,沒有辦法將快取設定為永久存放,像是做討論區的文章,通常熱門的文章在短時間會被重複的讀取,但熱度可能會隨著時間做遞減,可能大約 3 天的時間文章就會變得越少人存取,當沒有人存取的時候,我們就會希望將快取清除,避免佔住系統資源(記憶體或硬碟容量),所以我們可能會針對討論區的文章做 3 天時間的快取,等超過 3 天 後,快取會自動地將過期的快取資料做清除,除非又有人再次讀取該篇文章,才會再做一次快取(失效時間再次設為 3 天),一直重複這樣的動作,等到資料不再被存取,就只會保留在資料庫的洪流當中。
### 手動清除快取
在部落格發表的文章被讀取時,我們會對文章進行快取,但有時文章可能因為作者「打錯字」或者「需要補充資料」,導致文章需要被異動更新,為了能夠讓快取有最新被異動過的資料,通常我們會手動的清除這篇文章的快取,這樣就可以確保下一個存取這篇文章的讀者,一定會拿到最新的文章資料。
### 資料分散式快取
快取的資料通常是用 `key` 及 `value` 的方式去紀錄資料,而我們通常會把資料做片段的快取,像是部落格文章 A 的快取我們通常會存放在 `key` 為 `blog_post:post_id_A` 的快取資料中,以此類推,文章 B 的快取 `key` 為 `blog_post:post_id_B`,用這樣的方式對每個不同的小資源去做快取,而不是將所有部落格文章 A 及 B 存放在一整個快取 `key` 為 `blog_post:all` 中,因為當使用者異動文章 A 的時候,若我們要刪除快取的資料則只需要刪除文章 A 的快取即可,而不需要把其他不必要刪除的文章快取也一併刪除了,提高快取使用的效率,通常要看自己的應用及使用者存取資料的方式,需要用哪一種方式的快取比較適合,每一種應用都有適合自己的快取方法。
### 參考資料
- [一步步構建大型網站架構- 架構設計- | 九街| 白開水的博客](http://www.9streets.cn/art-php-489.html)
頁面片段暫存
最后更新于:2022-04-01 06:10:11
# 頁面片段暫存
在我們將靜態頁面暫存起來後,減少了很多對資料庫不必要的存取,`回應時間` 提升了了很多。
但我們也會想看看能不能在動態產生的頁面中,對於部分的很少變動的資料也做暫存的處理,這樣的話就可以減少部分動態網頁頁面不必要的存取了。
**_架構圖:_**
![頁面片段暫存](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2015-08-11_55c9661b98d41.png)
### 參考資料
- [一步步構建大型網站架構- 架構設計- | 九街| 白開水的博客](http://www.9streets.cn/art-php-489.html)
前端靜態頁面暫存
最后更新于:2022-04-01 06:10:09
# 前端靜態頁面暫存
當越來越多人來存取你的應用時,你會發現你服務的 `反應時間` 又開始變慢了,你可以會發現 `Web` 機器效能的使用沒有 `Database` 那麼大,就會發現現在的瓶頸應該是卡在 `Database` 有太多人去進行存取了。
我麼這時候會試著將頁面中很少異動的頁面(大約 1~2 天才會更新的頁面),做成靜態頁面的快取,在撈取資料庫資料時把資料產生成靜態 HTML 檔案,當下次再次的讀取相同資料時,則直接將靜態的 HTML 回傳,減少資料庫的存取,提高存取資料庫的效率(有需要再去進行查詢)。
**_架構圖:_**
![前端靜態頁面暫存](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2015-08-11_55c9661b8b883.png)
### 注意事項
### 整頁靜態頁不可頻繁的修改
因為會將整個頁面都做是要給使用者看到的整個結果頁,所以頁面的資料若時常修改的話,則勢必要一直重新產生新的靜態頁面,但這樣就失去了做靜態頁面暫存的意義了
### 參考資料
- [一步步構建大型網站架構- 架構設計- | 九街| 白開水的博客](http://www.9streets.cn/art-php-489.html)
Web 與 Database 分手
最后更新于:2022-04-01 06:10:06
# Web 與 Database 分手
當服務越來越多人需要去同時存取時,原本的 `Web` 與 `Database 在一起` 的架構會變得不敷使用了,網站的 `反應時間` 會變得越來越慢,伺服器的 `CPU` 及 `記憶體` 的消耗也會變得越來越高。
而且服務彼此還會互相搶機器的資源,若機器發生問題導致資料庫的資料也出現問題,會造成的麻煩會變得更大,於是我們就會想要把 Web 與 Database 的機器相互分離。
當用這樣的架構之後,你會發現效率會比之前提高很多,服務彼此不會搶資源了,但是就是要付出 $ 去添購機器摟(當可以用 $ 解決的問題都是小問題)
**_架構圖:_**
![Web 與 Database 分手](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2015-08-11_55c9661b80db9.png)
### 使用時機
### 同時上線人數約 20 ~ 40 人左右
**_人數為 KeJyun 過去經驗大概估算的人數,沒有經過實際測試僅參考用_**
當我們的服務能夠尤多台機器去分攤時,機器彼此的處理效率當然就會提高許多,可以乘載的人數也會提高
以飲料店來當例子,1 個服務生可以同時服務 3 位客人(主機同時有 3 個人發出請求),但是若有 2 位服務生就可以同時服務 6 位客人(主機同時有 6 個人發出請求),將替客人做點餐結帳、做飲料的工作做分工處理,一為服務生同時可以替 6 位客人做點餐結帳的工作,另一位則可以同時替 6 為客人做飲料,整個服務可以乘載的量就會提高很多,讓每個人專心做一件事情,效率也會提高很多
> 同時上線非每日上限,同日上線指的是同一時先有多個人同時跟伺服器要資源
### 需要維持一定的服務可用度
當服務需要提供比較多人去做存取時,我們就必須要提供一定水準的服務可用度,將反應時間保持在 1 ~ 2 秒內的範圍。
### 資料定期備份
雖然服務還在剛起步的階段,但是資料還是非常重要的公司資產,若只有一台 Database,我們還是需要定期的將資料備份出來(最少 1 天備援一次),避免機器掛掉的機會。
### 參考資料
- [一步步構建大型網站架構- 架構設計- | 九街| 白開水的博客](http://www.9streets.cn/art-php-489.html)
Web 與 Database 在一起
最后更新于:2022-04-01 06:10:04
# Web 與 Database 在一起
把 Web 或 Database 弄在同一部機器這樣的方式,通常是用在程式開發的「本地測試機」中,或者通常不會`同時`拿來服務太多的人的應用(共同上線人數),像是一般基本的公司形象網站、個人介紹頁...等等不會有太多人同時存取的資料懷鏡時才會使用這樣的架構。
除了基本的 Apache(Nginx)及 MySQL(Postgres),視情況需要設置會把其他的服務也放在同一台機器,像是 Memcached、Redis、Node.js。
**_架構圖:_**
![Web 與 Database 在一起](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2015-08-11_55c9661b75d9b.png)
### 使用時機
### 同時上線人數約 10 ~ 15 人左右
**_人數為 KeJyun 過去經驗大概估算的人數,沒有經過實際測試僅參考用_**
當一台機器需要乘載多種服務時,同樣的主機資源要做很多事情,當然處理的效率通常都比較低
以飲料店來當例子,1 個服務生可以同時服務 3 位客人(主機同時有 3 個人發出請求),同時替客人做點餐結帳、做飲料的工作,但是當客人越來越多時來到 15 人的時候,因為人的能力有限(主機的效能有限),所以後面很多人就需要排隊等前面幾位客人拿到飲料後才能繼續服務,所以就需要等待排隊(主機回應時間拉長),所以要看自己的經濟規模(同時乘載規模)去聘請適當人數的員工(規劃使用不同的主機架構)
> 同時上線非每日上限,同日上線指的是同一時先有多個人同時跟伺服器要資源
### 服務的可用度不需要太高
大部份的使用者可能最高能夠忍受等待[一貶眼的時間](http://news.networkmagazine.com.tw/news/2012/03/02/38107/)(約 250 毫秒 = 0.25 秒),但是這個標準是在產品一秒鐘幾十萬上下時才需要達到的可用度標準(像是股票交易、電子商務網站、社群網站...等等),一般只是測試用或是形象的網站不需要那麼高的可用度,能夠在 1 ~ 2 秒內回應都是在可接受的範圍(當然不能太久超過 4、5 秒以上,使用者會以為網站掛掉了沒有回應)
### 資料有做異地備援
資料可以說是整個企業的資產及生命,當資料自己有做異地備援的話,就可以用這樣的方式,不然主機太操很容易掛掉(就像人一樣加班太久沒休息,就很容易生病),裡面的資料可能會因為沒辦法救回,所以若是有做資料備份,不怕資料不見的狀況下再去用這樣的架構去做服務。
### 參考資料
- [你願意花多久等待網站回應? 一貶眼都嫌太久了](http://news.networkmagazine.com.tw/news/2012/03/02/38107/)
- [瞭解網站速度 - Analytics (分析) 說明](https://support.google.com/analytics/answer/2383341?hl=zh-Hant)
網站架構演進
最后更新于:2022-04-01 06:10:02
# 網站架構演進
這裏會介紹從小型網站到大型網站整個的架構,是怎麼規劃及演進的。
檔案
最后更新于:2022-04-01 06:10:00
# 檔案
我們可能會需要產生圖片或檔案供使用者去下載,這些讓使用者可以公開存取檔案的原則大概有這些:
- 隨機檔名
- 同一目錄下不要有太多檔案
- 資料庫僅儲存圖片檔名,不要紀錄完整路徑
- 使用 CDN 提高負載平衡及降低頻寬成本
# 隨機檔名
很多人可能會圖方便,讓檔案用可以猜出規則的方式做儲存,例如有人可能在儲存會員的照片,是用會員的編號當作圖片檔名,如果會員編號是整數的欄位,則就更容易讓人家猜出來,更方便地去解析你主機的所有會員照片,像是:
~~~
100000001.png
100000002.png
100000003.png
...
100999999.png
~~~
所以通常我們會將圖片的名稱依照會員編號的規則去做加密,我們可能可以用 md5 去做加密的動作,這樣圖片檔名可能會像是:
~~~
d69d3401d01a8ceed4549434e5ad9f40.png (`100000001` md5)
5a5ea04157ce4d020f65c3dd950f4fa3.png (`100000002` md5)
154666111ab87ce13405f384faeb5428.png (`100000003` md5)
...
e0b50eb5c4add211417977e1f79364e0.png (`100999999` md5)
~~~
這樣圖片的檔名看起來隨機了許多,比較不容易被猜出來,但是對比較厲害的人,可能會想要拿你的會員編號自己做 md5,所以還是可以看出規則,這時候我會試著在 md5 的會員編號字串加自定義的 salt 字串像是 `KeJyun`,這樣出來的圖片檔名會像這樣:
~~~
a3bce35e2b4e57911869b1bf5d040d71.png (`100000001KeJyun` md5)
5121a0fabb52c26c01817ee65df683a8.png (`100000002KeJyun` md5)
2ec12af8e6e011a0f5256b61db2145c3.png (`100000003KeJyun` md5)
...
467bd65bf6d4864adcc633caf2a70f7d.png (`100999999KeJyun` md5)
~~~
這樣除非對方知道我們使用哪一個 salt 去做加密,否則就很難被猜出來
### 同一目錄下不要有太多檔案
我們存放會員大頭照的路徑可能會像是: `http://www.kejyun.com/users/images/a3bce35e2b4e57911869b1bf5d040d71.png`
在上面的例子我們把所有的會員照片都存放在 `users/images` 的目錄下,對於系統程式,我們可以很快的指定路徑去讀取該檔案出來,但如果對於系統端的管理者,要去管理這些檔案時就會造成很大的困擾,想像你有 1000 萬個會員照片,所有的會員照片都放在同一個目錄下面,光是要使用 `ls`指令去列出那個目錄的所有照片,對於系統來說就是一大夢靨...
所以我們通常會對檔案做資料夾的分層處理,像是 `a3bce35e2b4e57911869b1bf5d040d71.png` 檔案,我們可能取其前 3 個字元 `a3b` 去做資料夾的分層,所以我們圖片會份在 `users/images/a3b/a3bce35e2b4e57911869b1bf5d040d71.png` 目錄下,分層資料夾的 3 個字元的[資料排列組合](#)為 `46,656` 種,所以若我們有 `1000 萬`個會員照片,我們可以預期照片會被平均的放在到各個分層資料夾,每個分層資料夾約 `214 張`照片 `(10000000 / 46625 = 214.33)`,這樣對於系統在做檔案的索引及瀏覽也會比較快。
資料夾的分層要如何分層,完全取決於你系統專案資料數量的需求,若你預期你的檔案會超過 1 億種,那麼分層方式我們可能會分成 2 層,依照上面規則,照片可能會被放到 `users/images/a3bc/e35/a3bce35e2b4e57911869b1bf5d040d71.png` 下面,要怎麼分層處理完全取決於你的需求狀況,沒有一定的規則!
### 資料庫僅儲存圖片檔名,不要紀錄完整路徑
我們的檔案可能會隨著系統使用人數變多,需要轉換成不同的管理方式,所以檔案在做大型專案時,很有可能會隨時被移動位置的,所以千萬不要將完整的圖片路徑存到資料表欄位中,否則以後在做檔案效能最佳化調校時,資料表檔案路徑還需要重新的異動更新,會是很大的難題,可能的瓶頸可能會卡在:
- 專案不能只為了調整圖片路徑而關站維護
- 資料量很大,更新檔案路徑很慢,可能需要 3~7 天以上去更新資料表的資料
- 若更新失敗,或者是又需要重調整架構時,所耗費時間會更長
所以我們在資料表只要紀錄檔案的檔名就好,所有與架構有關的資料通通由程式去控制產生,程式只要改一下,檔案的存取架構隨時都可以容易的做異動
### 使用 CDN 提高負載平衡及降低頻寬成本
我們的主機可能會使用 AWS、Linode 之類的雲端服務,這些的主機可能是放在日本或美國,我們希望使用者去距離使用者自己比較近的 CDN 主機,去存取這些不常被異動的靜態資料,這樣可以提高原本主機本身的負載流量,將流量做分散式的處理。
我們的圖片可能放在像是這樣的網址下:
~~~
http://cdn1.kejyun.com/users/images/a3bc/e35/a3bce35e2b4e57911869b1bf5d040d71.png
http://cdn2.kejyun.com/users/images/a3bc/e35/a3bce35e2b4e57911869b1bf5d040d71.png
http://cdn3.kejyun.com/users/images/a3bc/e35/a3bce35e2b4e57911869b1bf5d040d71.png
...
http://cdn9.kejyun.com/users/images/a3bc/e35/a3bce35e2b4e57911869b1bf5d040d71.png
~~~
這些不同的主機存放的圖片都與原主機的 `http://www.kejyun.com/users/images/a3bc/e35/a3bce35e2b4e57911869b1bf5d040d71.png` 相同,只是我們把同樣的靜態檔案分流複製到各個 CDN 主機上,這樣就不用讓原主機承載過高的頻寬吞吐量了!
### 參考網站
- [內容傳遞網路 CDN - Wiki](http://zh.wikipedia.org/wiki/%E5%85%A7%E5%AE%B9%E5%82%B3%E9%81%9E%E7%B6%B2%E8%B7%AF)
- [CloudFlare](https://www.cloudflare.com/)
刪除
最后更新于:2022-04-01 06:09:57
# 刪除快取
我們設定了快取希望使用者存取資料的時候能夠加快回應時間,但資料可能會因為使用者的`刪除`或`修改`而產生了異動,若我們需要讓使用者能夠讀取到最新的資料,我們通常會手動的將快取刪除,讓使用者下次讀取的話能夠去資料庫讀取到最新的資料,在重新設定一次新的快取資料。
### 以部落格文章快取為例
### 更新部落格文章資料
~~~
<?php
// 快取 key 依照不同的文章編號,可以是 blog_post:1 或 blog_post:2
$cache_key = 'blog_post:' . $post_id;
$results = DB::update('UPDATE `posts` SET `content`= ? WHERE `post_id` = ?', [$new_content, $post_id]);
if ($result) {
// 選擇1: 直接設定文章快取,讓下一位使用者再次存取相同文章時可直接取用快取
Cache::put($cache_key, $new_content, $cache_minutes);
// 選擇2: 刪除快取,等下一位使用者讀取文章時在去設定快取
Cache::forget($cache_key);
}
return $result;
~~~
### 刪除部落格文章資料
~~~
<?php
// 快取 key 依照不同的文章編號,可以是 blog_post:1 或 blog_post:2
$cache_key = 'blog_post:' . $post_id;
$results = DB::delete('DELETE FROM `posts` WHERE `post_id` = ?', [$post_id]);
if ($result) {
// 刪除快取,讓下一位使用者不要再讀取已被刪除的文章
Cache::forget($cache_key);
}
return $result;
~~~