翻一下 Linux container 的各種 overhead

想要查一下 Linux 下跑 container 的 overhead,發現大多都是 2014~2016 左右的文章,而且基本上都是 Docker,好像沒什麼新資料,但還是整理整理...

首先是「What is the runtime performance cost of a Docker container?」這篇,裡面的答案有提到 CPU、Memory 以及 I/O 看起來 overhead 都不高,主要是網路的 latency 增加不少:

看起來大約是 40µs 的增加 (0.04ms),這個量級雖然看起來很小,但對於本來就是透過 Ethernet 溝通的的應用來說,平常可能都是 <1ms 了,0.04ms 的增加可能還是有影響 (像是 TCP 的 3-way handshake)。

另外一篇是 Percona 的「Measuring Percona Server Docker CPU/network overhead」,不過這邊是測 CPU bound 的方式,沒有碰到 heavy I/O:

可以看到網路層的變化造成 tps 的變化,也符合在 Stack Overflow 上面找到的文章。

Oracle 官方的「MySQL with Docker - Performance characteristics」這篇則是測到 I/O bound 的應用,畢竟資料庫軟體會用到很多一般 I/O 測試不會用到的 flag,像是 InnoDB 大家通常都會啟用 O_DIRECT

For these tests, we used a custom configuration file. We first deliberately set the buffer pool size to around 10% of the total database size in order to increase I/O-bound load. The database size was 2358MB, so we set our buffer pool size to 256MB. We then increased the buffer size to 16384MB to see what happens when Docker isn’t bound by I/O load.

文章後面有列出數字,可以看到 I/O bound 的應用似乎沒有什麼影響,而 network bound 的時候可以看到效能的下降。

不過得注意這些資料都是六年前的資料了,沒有什麼新資料可以看做應該是沒什麼改變,但畢竟不是 100% 確定的事情...

在 Shell 下一行用 SQLite 查詢 CSV 內的資料

Simon Willison 這邊看到 command line 下用 SQLite 的技巧:「One-liner for running queries against CSV files with SQLite」。

範例指令是這樣 (整理了一下排版):

sqlite3 :memory: \
    -cmd '.import -csv taxi.csv taxi' \
    'SELECT passenger_count, COUNT(*), AVG(total_amount) FROM taxi GROUP BY passenger_count'

可以看出來這個方式是將 csv 檔先讀到 in-memory database (:memory:),再用 SQLite 下指令處理,另外也可以自己變化,應該可以透過 /dev/stdin 這樣的方式讀 pipe 的東西。

拿來簡單跑一些東西應該還不賴?

在 Hacker News 上看到幾個 Key-Value Store 軟體

Hacker News 上看到「Redis vs. KeyDB vs. Dragonfly vs. Skytable」這篇,裡面介紹了四套 key-value store 軟體:

  • Redis:這個應該不太需要介紹...
  • KeyDBSnapchat 搞出來的 Redis clone,主要的賣點是 multi-threading。
  • Dragonfly:宣稱地球上最快,但作者跑不出來,下面的討論有人提到 Dragonfly 在更多的 CPU 資源效能就會更好。
  • Skytable:作者測出來最快的。

裡面看起來都蠻有趣的,可以追起來看看發展的情況,但如果真的要的用的話,應該還是先以 Redis 為主,穩定度以及功能還是重點...

GCP 推出 AlloyDB,一套相容 PostgreSQL 協定的資料庫服務

也是在清 RSS reader 的時候翻到的,看起來是在今年的 Google I/O 上發表的服務,AlloyDB:「AlloyDB for PostgreSQL under the hood: Intelligent, database-aware storage」,值得提的是這篇有中文版可以看:「適用於 PostgreSQL 的 AlloyDB 隆重登場:從此擺脫成本高昂的老舊資料庫」。

另外還有一篇比較偏 PR 的文章也可以看看:「Introducing AlloyDB for PostgreSQL: Free yourself from expensive, legacy databases」,這篇就比較針對的提到了與 AWS 的服務相比,但畢竟是 PR 稿沒有明講 (出事會比較好打模糊戰),但我猜測是與 Aurora 對比:

AlloyDB was also two times faster for transactional workloads than Amazon’s comparable service.

宣稱在 OLTP 上快了兩倍 (原來的三倍?),但應該都是以 PostgreSQL 下去改,猜測可能是底層的 storage 與 replication 比較好?

AlloyDB 設計上是考慮了 HTAP (Hybrid transactional/analytical processing) 的使用,所以同時可以提供 OLAP 與 OLTP 的應用:

[...] This makes AlloyDB a great fit for business intelligence, reporting, and hybrid transactional and analytical workloads (HTAP).

直接在一個資料庫內處理 OLAP 與 OLTP 這點的確會讓 AlloyDB 比 AWS 目前能提供的方案方便不少 (然後想一下 BigQuery 團隊...)。

目前在 AWS 對應的方案應該是透過 Redshift 來解決,另外一個方案是透過 Athena 來跑。

最後來看價錢,如果效能變成兩倍但價錢也是兩倍的話,就代表在價格上沒優勢。

先看機器的部份,如果是拿 Aurora 這邊 Intel-based 的 db.r5.24xlarge (96 vCPU + 768 GB RAM) 來算的話是 US$13.92/hr,而如果換算到 AlloyDB 的話是 US$14.94528/hr,相除是 0.9314,大約 7% 的差距,可以算是同一個級距。

如果 Aurora 這邊是拿 ARM-based 的 db.r6g.16xlarge (64 vCPU + 512 GB RAM) 來算的話是 US$8.306/hr,換算到 AlloyDB 的話是 US$9.96352/hr,相除是 0.8336,這邊就差超過 16% 了...

(這邊剛好回顧一下 "Amazon’s comparable service" 這段,不確定他是跟 Intel-based 比還是跟 ARM-based 比,畢竟 ARM 除了比較便宜外,還有效能的提昇)

但最大的差異應該是在 storage 相關的部份。其中 Aurora 這邊的空間與 I/O 是分開收費的,以 us-east-1 來說,storage 是 US$0.10/GB/mo,而 I/O 是 US$0.20/million-requests,在 AlloyDB 這邊來說,Regional cluster storage 是 US$0.0004109/GB/hr (us-east4),變成是 US$0.295848/GB/mo,兩邊相比後可以算出來對等的計價會是 AWS 的 storage 加上 AWS 給你 1.47M 的 I/O (per GB)。

這樣算起來把資料丟 S3 跑 Athena 可能不會比較貴... (當然效能是另外的主題了)

光就檯面上的資料來看,看起來是個不錯的東西,等後續有人跳進去用看看感想...

Cloudflare 的 D1 (SQLite as a service)

Hacker News Daily 上看到 Cloudflare 推出了新產品 D1:「Announcing D1: our first SQL database」,在 Hacker News 上對應的討論在「D1: Our SQL database (cloudflare.com)」這邊可以看到。

就如同 Hacker News 上的討論提到的,這篇文章不像一般的 Cloudflare 文章會帶有很多技術上的說明 (尤其是在描述技術產品),這篇算是非常的行銷導向的文章,目前大家只能靠「猜」的去理解:

For a Cloudflare article, this one is surprisingly light on technical details. And for the product where it most matters.

翻了一下這兩個屬名的作者,Rita Kozlov 是 Director of Product at Cloudflare,而 Glen Maddern 是 Systems Engineer at Cloudflare。

目前知道的是,D1 是架構在 SQLite 上面:

D1 is built on SQLite.

然後從範例的程式碼內可以看到,在 JavaScript 裡面的用法是透過 await env.DB.get() 操作:

export default {
  async fetch(request, env, ctx) {
    const { pathname } = new URL(request.url)
    if (pathname === '/num-products') {
      const { result } = await env.DB.get(`SELECT count(*) AS num_products FROM Product;`)
      return new Response(`There are ${result.num_products} products in the D1 database!`)
    }
  }
}

然後從 screenshot 上沒有看到 region,但是 class 那邊出現了一個 tokyo3 不知道是什麼東西:

目前看到的就這些,沒提到 replication 機制 (這其實還蠻重要的,某些資料是有法規限制的),另外開發者會很在意的 performance 或是 latency 也沒提到 (所以可以預期應該不會太好?)。

另外在 RDBMS 內很重要的 ACID 特性與分散式系統中 CAP theorem 的性質也都沒有分析。

可以先放著看看就好...

Amazon RDS for PostgreSQL 可以掛 155 台 Read Replica

看到 AWS 推出的新「功能」,可以讓 Amazon RDS for PostgreSQL 的 read replica 掛到 155 台:「Amazon RDS for PostgreSQL supports cascaded read replicas for up to 30X more read capacity」。

作法是透過三層架構,每台機器可以堆五台 replica:

Amazon Relational Database Service (Amazon RDS) for PostgreSQL announces support for PostgreSQL 14 with three levels of cascaded read replicas, 5 replicas per instance, supporting a maximum of up to 155 read replicas per source instance.

需要 PostgreSQL 14.1 或是之後的版本:

Starting with Amazon RDS for PostgreSQL 14.1 and higher, read intensive workloads such as data analytics can now benefit from up to 155 cascaded read replicas that offer up to 30 times higher read capacity versus previous versions of PostgreSQL, thereby reducing the load on source instance.

我記得 Amazon RDS for PostgreSQL 的 replica 是 EBS block-level replication,這種搞法還蠻有趣的 XDDD

在 PostgreSQL 上直接掛 ML extension

Hacker News 首頁上看到「Show HN: PostgresML, now with analytics and project management (postgresml.org)」這個專案,可以在 PostgreSQL 上面直接掛 extension 跑 ML algorithm:「PostgresML - an end-to-end machine learning solution」,從 GitHub 上可以看到大多數是 Python 的程式碼。

從 GitHub 頁面上面可以看到這個專案還在比較早期的階段:

This project is currently a proof of concept. Some important features, which we are currently thinking about or working on, are listed below.

如果是目前要用的話,主要是方便看一些東西吧?可以想到的是掛個 replication 出來跑一些 query,這樣不會影響到 production database 的效能,應該還行...

另外看了一下支援的演算法,主要是以經典的 ML 演算法為主,而且就是套用 Python 上面的套件:XGBoostscikit-learn

這些演算法算是很好用了,而且掛到 PostgreSQL 裡面會讓使用上方便很多 (少了倒資料的動作,不過就得小心處理 dirty data 了),然後專案也附上一個 UI 界面可以看一些資料,不過我猜還是用其他生 visualization 的工具會比較豐富一點:

另外一個想法是拿來學習還不錯?老師在上課的時候拿來示範一些演算法,就不用自己再刻很多程式碼...

低 Downtime 將 4TB 的 PostgreSQL 9.6 資料庫升級到 13 的故事

前幾天在 Hacker News 首頁上看到的文章,講怎麼把一個 4TB 的 PostgreSQL 從 9.6 升級到 13 的故事:「How we upgraded our 4TB Postgres database (retool.com)」,原文在「How Retool upgraded our 4 TB main application PostgreSQL database」,翻了一下 LinkedIn,這篇文章的作者 Peter Johnston 在 Retool 掛的是 Security Software Engineer,另外他也有在 Hacker News 上的討論出現 (帳號是 mrbabbage),可以搜尋翻翻看他的回覆。

看完文章後發現方法的概念其實不難,主要是要找到對的工具來用。基本的想法是先生出一個 initial dump,然後架構 logical replication,接下來就是處理各種因為在 4TB data 這個 scale 下會遇到的問題。

主要用到的工具是 Citus Data 的 Warp:「Citus warp: Database migrations without the pain」,不過這個工具的限制是表格必須都有 single column primary key,所以他們為了這次轉移也有小改 database schema 配合 Warp 的要求:

We had to do a bit of finagling to coax Warp into processing our database. Warp expects all tables to have a single column primary key, so we had to convert compound primary keys into unique constraints and add scalar primary keys. Otherwise, Warp was very straightforward to use.

另外針對比較大的兩個 append-only 的表格 (分別是 2TB 與 x00 GB) 做處理,在 initial dump 的階段不對這兩個表格做 replication,而是透過自製的 Python script 搬移:

To handle the two massive tables we skipped in Warp, we wrote a Python script to bulk transfer data from the old database server to the new.

然後是 foreign key 相關的關閉與重啟,這算是 RDBMS 在大量資料的 dump & restore 的標準作業了:

As you can see from the runbook above, one of the steps we had to do was to turn off and then re-enable foreign key constraint checks.

最後執行下去,整個 downtime 只有十五分鐘:

We scheduled the maintenance window late on Saturday, October 23rd, at the lowest period of Retool cloud traffic. With the configuration described above, we were able to bring up a new database server at version 13 in around 15 minutes, subscribed to changes at our 9.6 primary with logical decoding.

另外也有提到有計畫要 sharding,之後 main database 就有機會被拆小:

We anticipate we’ll have sharded our database by the end of that support window, and be performing our next substantial version upgrades incrementally.

整個計畫的核心概念不難,主要是要怎麼順出來並且執行...

PHP (以及 Laravel) 下使用 DynamoDB 的 ORM 工具

Twitter 上看到「Laravel DynamoDB Eloquent Models and Query Builder」這篇文章,裡面講「Laravel DynamoDB」這個套件,可以在 PHP (以及 Laravel) 下存取 DynamoDB

雖然套件提到了 Laravel,但文件裡面也有提到支援非 Laravel 的 PHP 環境下使用,單獨拿出來用也沒問題,比較重要的反倒是 DynamoDB 對各種 key 的概念。

如果是從零開始設計,但又不想要自己管資料庫,我會偏好先用 RDS 設計,無論是 MySQL 或是 PostgreSQL 的版本都行,畢竟 RDBMS 上面能做的事情比較多,對開發者比較友善,除非是第一天上線你就預期量會大到連 db.m5.24xlarge 都擋不住之類的情況...

這個月 GitHub 的不穩問題,都是 mysql1 這個 cluster 的鍋...

GitHub 針對了這個月的四次 downtime 說明,大致上都跟 mysql1 這組 cluster 有關:「An update on recent service disruptions」,這是 Keith Ballinger 發的文章,找了一下掛的頭銜是 SVP of Engineering at GitHub。

文章裡提到的 mysql1 在「Partitioning GitHub’s relational databases to handle scale」這邊可以看到一些資訊 (我在「GitHub 的 MySQL 架構與數字」這邊也有提到),基本上有 ProxySQL + Vitess 兩套方案在 scale,但可以看出來主資料庫本身還是有很大的 loading 在上面跑。

這次的問題是 mysql1 看起來這次遇到了效能上的瓶頸,不過還是沒找到原因,這可以從這幾次的說明看出來,從第一次的 outage:

The incident appeared to be related to peak load combined with poor query performance for specific sets of circumstances.

第二次的:

The following day, we saw the same peak traffic pattern and load on mysql1. We were not able to pinpoint and address the query performance issues before this peak, and we decided to proactively failover before the issue escalated.

第三次的:

While we had reduced load seen in the previous incidents, we were not fully confident in the mitigations.

In this third incident, we enabled memory profiling on our database proxy in order to look more closely at the performance characteristics during peak load.

到最近第四次的:

In order to reduce load, we throttled webhook traffic and will continue to use that as a mitigation to prevent future recurrence during peak load times as we continue to investigate further mitigations.

可以看到基本上還沒完,之後再遇到問題時應該還是會把 webhook traffic 拿出來開刀...