Etsy 介紹的 Cache Smearing

Etsy 的 engineering blog 上提到了他們怎麼設計 cache 機制:「How Etsy caches: hashing, Ketama, and cache smearing」。

使用 consistent hash 已經是基本款了,文章裡花了一些篇幅介紹為什麼要用 consistent hash。

後半段則是有了 consistent hash 後會遇到的問題,也就是講 hot key 怎麼處理:有些資料非常熱 (常常被存取),就算用 consistent hash 也還是有可能搞爆單一機器。

他們做了幾件事情,第一件事情是設計 cache smearing 機制,把單一資料加上 random key,使得不同的 key 會打散到不同的機器上:

Let’s take an example of a hot key popular_user_data. This key is read often (since the user is popular) and is hashed to pool member 3. Cache smearing appends a random number in a small range (say, [0, 8)) to the key before each read or write. For instance, successive reads might look up popular_user_data3, popular_user_data1, and popular_user_data6. Because the keys are different, they will be hashed to different hosts. One or more may still be on pool member 3, but not all of them will be, sharing the load among the pool.

第二件事情則是監控哪些 key 比較熱門:

We’ve seen this problem many times over the years, using mctop, memkeys, and our distributed tracing tools to track down hot keys.

第三件事情是維護 hot key 的清單 (不是每個 key 都會上 cache smearing):

We manually add cache smearing to only our hottest keys, leaving keys that are less read-heavy efficiently stored on a single host.

是個當規模大到單一 hot key 會讓單台伺服器撐不住時的 workaround...

HTTP/2 時代的 API 設計

在「Let’s Stop Building APIs Around a Network Hack」這邊提到了以前為了解決 HTTP/1.1 的問題而發展出來的 workaround,在 2015 年發展出來的 HTTP/2 從底層直接解了不少問題,加上很快被許多瀏覽器支援 (就算不支援 HTTP/2 也只是降到 HTTP/1.1 跑,比較慢而已):

Guess what else was released in May 2015? RFC 7540, otherwise known as HTTP/2. In retrospect this seems highly poetic, as HTTP/2 kinda makes the compound document aspect of JSON-API a little bit pointless, and compound documents to me go hand in hand with what JSON-API is as a standard.

2012 年在 MOPCON 第一屆講的「API Design Optimized for Mobile Platform」剛好就是這個主題:

有種懷念感... XD

在 Mac 上快速換輸入法的方法:Kawa

三月的時候在「在 Mac 上快速切換輸入法」這邊提到了 IMEShortcuts,但有時候還是不會生效...

在「GitHub 中那些不错的免费软件」這篇裡面提到了 open source 的 utatti/kawa 這個專案,裡面有針對 CJKV 輸入法的 bug 提供 workaround,就給個機會測試看看:

There is a known bug in the TIS library of macOS that switching keyboard layouts doesn't work well when done programmatically, especially between complex input sources like CJKV.

而且最近變得可以用 Homebrew 管理了,這樣之後升級比較方便。

Amazon EC2 要推出 x1e.32xlarge,4TB RAM 的機器

剛剛 Amazon EC2 公佈的消息,要再推出記憶體大怪物機器 x1e.32xlarge:「EC2 In-Memory Processing Update: Instances with 4 to 16 TB of Memory + Scale-Out SAP HANA to 34 TB」。

Later this year we plan to make the x1e.32xlarge instances available in several AWS regions, in both On-Demand and Reserved Instance form. These instances will offer 4 TB of DDR4 memory (twice as much as the x1.32xlarge), 128 vCPUs (four 2.3 GHz Intel® Xeon® E7 8880 v3 processors), high memory bandwidth, and large L3 caches.

雖然都是拿 SAP 來舉例,但這也是當系統碰到瓶頸時搶時間的方法 (也就是當 happy problem 發生時的 workaround)。

不知道這種機器實際買起來多少錢 XDDD

IPFS 分散式 Web 服務,以及 ipfspics 圖片儲存

IPFS (InterPlanetary File System),或是被稱作 The Permanent Web。

起因在於目前 HTTP (Web) 在設計時是 1990 年代的想法,許多威脅在當時並不明顯。而到了現在,來自攻擊者的威脅與政府監控的威脅使得必須在 HTTP (Web) 上架構許多 workaround。

最知名的 workaround 就是 HTTPS 以及對應的 CA 架構了,前者因為 HTTPS 協定本身高度複雜,實作的單位經常出錯而產生安全漏洞。而後者靠著大量的稽核檢查來避免出問題,不過畢竟還是 workaround,常常會有一堆「誤發」的狀況發生。

另外 HTTP 發展到現在其實是去中心化「Decenteralized」的架構,政府單位可以抓著其中幾個結點就可以大量監控,而 IPFS 想要做到真正的分散式「Distributed」:

前陣子 IPFS 在 GitHub 上放出了 prototype 讓大家玩:「ipfs implementation in go.」,而最近有人把這個點子實作成 image hosting:「ipfs.pics」(一樣是放在 GitHub 上),並且提供對應的網頁上傳介面:「Decentralized picture hosting in ipfs」。

我試著丟一張圖片上 ipfs.pics 後,得到的 hash 值是 QmRpNqK33gDDKdu8y6Wx5DQsuiJbsnwojNzH5nUwCpwoS9,也可以在 IPFS 看到這張圖:

來玩看看好了 :o

Adobe Typekit 支援 CJK 字型

Adobe Typekit 宣佈支援 CJK 字型:「Announcing East Asian web font support and new font browsing tools for Japanese customers」。中文的公告在「正式公開東亞網頁字體支援以及日文客戶適用的全新字體瀏覽工具」這邊。

這也包括了網頁版的部份。對於 CJK 單一字型檔案過大的問題,與大家的解法也都一樣,取出對應的字組出來給使用者作為 workaround (稱為 Dynamic Subsetting):

會稱為這是 workaround 是因為當網路速度愈來愈之後,就會又變成最單純的直接整包下載...

Anyway,Adobe 這個新功能是一個大邁進,不過他用的 HTTPS (EdgeCast) 還沒支援 SPDY 或是 HTTP/2 啊... :/

關於 jquery-latest.js...

jQuery 官方希望大家不要再使用 jquery-latest.js 了:「Don’t Use jquery-latest.js」。

由於他們發現有大量的網站使用 jquery-latest.js,如果直接照著字面上的意思升級到 2.0,會造成這些網站在 IE{6,7,8} 上爛掉:

To mitigate the risk of “breaking the web”, the jQuery team decided back in 2013 that jquery-latest.js could not be upgraded to the 2.0 branch even though that is technically the latest version. There would just be too many sites that would mysteriously stop working with older versions of Internet Explorer, and many of those sites may not be maintained today.

所以官方已經決定將這個檔案鎖定在 1.11.1 版:

As jQuery adoption has continued to grow, even that safeguard seems insufficient to protect against careless use of http://code.jquery.com/jquery-latest.js. So we have decided to stop updating this file, as well as the minified copy, keeping both files at version 1.11.1 forever. The latest released version is always available through either the jQuery core download page or the CDN home page. Developers can download the latest version from one of those pages or reference it in a script tag directly from the jQuery CDN by version number.

同時,這個決策得到 Google CDN team 的支持,所以 Google CDN 上的 http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.js 也將鎖在 1.11.1:

The Google CDN team has joined us in this effort to prevent inadvertent web breakage and no longer updates the file at http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.js. That file will stay locked at version 1.11.1 as well. However, note that this file currently has a very short cache time, which means you’re losing the performance benefit of of a long cache time that the CDN provides when you request a full version like 1.11.1 instead.

同時官方也再三宣導,請不要用 jquery-latest.js 了,應該在使用時指定版本號碼。

這個決策算是一種 workaround,避免全世界一堆網站爛掉...

RAID 卡的電池維護

實際的世界都是由 workaround 疊 workaround 解決問題的...

MySQL 資料庫一般都用 RAID 10,利用 RAID 1 的特性保護資料,並且利用 RAID 0 的特性提昇 IOPS 能力。

而這些 RAID 卡通常都會提供 cache,預設應該都會開 read cache,可以大幅增加 random read 的速度。而另外也可以打開 write cache (也就是 write-back),寫入時先寫到 cache 裡,RAID 卡馬上就會跟作業系統回報完成,藉以加速 random write 的速度。

但這樣就會有風險,當資料還沒寫入硬碟就斷電時就會遺失資料。所以在設定 write-back 的 RAID 卡上安裝電池就變成解法之一。

而電池會有壽命問題,所以配電池的 RAID 卡會每隔一陣子就放電測試電池可以撐多久,但在放電測試時,如果斷電就有可能造成資料遺失,於是又冒出很多方法解決。

也就是在「Learning to Deal With Learning」這篇提到 RAID 卡電池維護的事情。

每一層都是 workaround 想辦法解決問題,然後再用 workaround 解決前面造成的問題...

Anyway,有幾種解法,其中仍然對上層作業系統與應用程式透明的解法是:

  • 雙電池架構,很明顯的可以一次只測一顆。
  • 改用 NVRAM,就不需要電池了,不過速度以及成本會是另外一個問題。

另外,對上層作業系統與應用程式有影響的方式:

  • 放電測試時將 write cache 關閉,切回 write-through。這點在原文裡也有提到,效能其實會受到蠻大的影響。
  • 不放電測試了,但這樣的缺點就是拿安全性交換,當斷電時不知道能不撐過去。
  • 或是自己控制放電測試的時間,這可以配合上面切回 write-through 的方式,挑負載比較輕的離峰時間做。

看了下來雙電池架構還不錯,增加的成本還算可以接受,而且因為效能不受到影響,也確保資料安全性,整體維護起來比較簡單。而之後在規模更大的時候,應該就會直接考慮跳到自己放電測試的方式來處理電池問題...

Domain Sharding 的調整...

Domain Sharding 是針對以往瀏覽器常見的「加速技巧」(workaround),目的是突破瀏覽器對單一 domain 的最大連線速限制。像是 IE{6,7} 在 HTTP/1.1 上的限制是 2。

Steve Souders 在 2008 年整理的「Roundup on Parallel Connections」就有列出當時各瀏覽器的限制。而在 BrowserscopeNetwork 可以看到更多新的數字。

而隨著環境一直在改變,桌機限制的連線數也逐漸調高,以及 SPDY 的發展,再加上行動平台的比重愈來愈高,本來的 Domain Sharding 技巧需要重新審視。

Etsy 的「Reducing Domain Sharding」這篇文章中提到他們決定減少 Domain Sharding 的數量 (由四個變成兩個),而改善了反應時間:

  • 在圖片較多的頁面上約減少 50ms~80ms,在一般頁面則是減少 30ms~50ms。
  • 在行動平台上減少 500ms。

這兩個改善使得每次造訪的點閱率多了 0.27 page。

尤其是行動平台上對 Domain Sharding 的敏感程度,讓現在設計網站的人要考慮的更多了...