Memcached 與 Redis 的比較

在「Memcached vs Redis - More Different Than You Would Expect」這邊看到對 MemcachedRedis 的分析。

這兩套軟體都很常被拿來用作 cache 機制,所以一般來說比較時就是比兩邊都有的東西 (如果你要 pub-sub 之類的東西,在這兩套裡面只有 Redis 有)。

最前面還是先講了對使用者 (開發者) 的差異,很明顯的是 Redis 對各種不同的資聊結構都有支援,這點可以從 Redis 被官方被稱作 Data Structures Server 就可以知道 (在「An introduction to Redis data types and abstractions」這篇可以看到),而 Memcached 只支援了 key-value 架構。

不過如果是以 cache 來說,的確 key-value 架構就還蠻好用的。

後面就開始比較硬的主題了,提到了 Memcached 與 Redis 內部是怎麼使用記憶體的。

Memcached 的部份先提了 page/slab/chunk 的架構以及產生的效能限制與浪費,接著有提到 2020 年 refactor 的部份 (太久沒有看 Memcached 的消息,去年沒跟到這個部份),讓多 CPU 的支援度更好。

Redis 則是靠 jemalloc 來處理這個部份,另外加上 background thread 的機制降低 fragment。

然後是比較 cache expiration 的部份,可以看到兩者用的演算法在現實世界中都夠用 (尤其是當作 cache 來用),這部份跟印象中的架構差不多,應該是沒有太大變化。

最後是比較 cluster 的部份,Memcached 是 share nothing,所以沒什麼好說的,主要是靠 client library 實做 consistent hash 之類的架構打散;而 Redis 的話看起來有實做新的機制出來 (也沒跟到),之後有機會再看看可以做到什麼程度。

不過好像沒提到 proxy 之類的架構,基本上各大公司都有自己幹:

少了這塊對於 cluster 架構的完整性差蠻多的。

文章最後沒有下定論一定要用哪個比較好,兩者都有強項與弱項,還是得看情況來處理。不過我自己還是很喜歡用 Memcached 就是了...

Amazon SES 總算支援 2048 bits RSA key 了

Amazon SES 總算是支援 2048 bits RSA key 了:「Amazon SES now supports 2048-bit DKIM keys」。

然後講一些幹話... 隔壁微軟早在 2019 年就支援 2048 bits RSA key 了:

Until now, Amazon SES supported a DKIM key length of 1024-bit, which is the current industry standard.

另外用 ECC 演算法的一直都沒進 standard,像是已經先 book 了 RFC 8463 位置的 Ed25519,在 draft 狀態放好久了:「A New Cryptographic Signature Method for DomainKeys Identified Mail (DKIM)」,還有用 ECDSA 的「Defining Elliptic Curve Cryptography Algorithms for use with DKIM」也是放著,不知道是卡到什麼東西,可能是專利?

2019 年 Percona 對 UUID 當作 Primary Key 的看法

前陣子的「為資料庫提案新的 UUID 格式」這邊提到了有人提案要增加新的 UUID 格式,Percona 的老大 Peter ZaitsevTwitter 上貼了「UUIDs are Popular, but Bad for Performance — Let’s Discuss」這篇在 2019 年時他們家的文章,題到了 MySQL 使用 UUID 當作 Primary Key 的事情:

要注意的是這篇文章沒有要從頭解釋 UUID 對於 Primary Key 的壞處,如果你想要先了解的話,在這篇文章的開頭給了一堆其他文章的連結,裡面就有討論過了。

這篇主要是在討論,如果硬要用 UUID 當 Primary Key 時,可以有什麼方法降低對 InnoDB 的衝擊,剛好回應最近的提案。

開頭還是先花了一些篇幅大概講一下 UUID 的種類,然後在「What is so Wrong with UUID Values?」這邊提到了字串比較的差異,如果 UUID 是到最後一碼才不同的話 (這邊是跑 df878007-80da-11e9-93dd-00163e000002 與 df878007-80da-11e9-93dd-00163e000003 與比較一億次):

1 row in set (27.67 sec)

但如果是一開始就不同的話 (這邊是選擇 df878007-80da-11e9-93dd-00163e000002ef878007-80da-11e9-93dd-00163e000003) 會快很多:

1 row in set (2.45 sec)

但如果與數字相比的話 (這邊是 2=3 這樣的條件去比):

1 row in set (0.96 sec)

可以看數字在這邊的優勢,另外也是在說明,如果你用的是 time-based ordering 的 UUID,要考慮會遇到這個可能會發生的效能問題。

再來是玩 UUID 的三種不同的儲存方式對於寫入效能的差異,分別是 CHAR(36) (32 bytes 的 hex 加上四個 -)、base64 (用 CHAR(22) 存) 與 BINARY(16),可以看出來 BINARY(16) 因為佔用空間比較小的關係,是可以高速寫入持續最久的,再來是 base64,最差的是 CHAR(36)

後面給了兩個 workaround,第一個算是定義了另外一種產生 128 bits 的方式,第二個則是想辦法把 UUID 對應到數字。

這在 MySQL 的環境裡面算是被討論的很久的主題了。(我猜在 PostgreSQL 應該也是,不過 PostgreSQL 的社群沒跟那麼久...)

為資料庫提案新的 UUID 格式

前幾天在 Hacker News Daily 上看到的東西,今年四月的時候有人針對資料庫提案新的 UUID 格式:「New UUID Formats – IETF Draft (ietf.org)」。

在 draft 開頭有說明這個提案的目標:

This document presents new time-based UUID formats which are suited for use as a database key.

A common case for modern applications is to create a unique identifier for use as a primary key in a database table. This identifier usually implements an embedded timestamp that is sortable using the monotonic creation time in the most significant bits. In addition the identifier is highly collision resistant, difficult to guess, and provides minimal security attack surfaces. None of the existing UUID versions, including UUIDv1, fulfill each of these requirements in the most efficient possible way. This document is a proposal to update [RFC4122] with three new UUID versions that address these concerns, each with different trade-offs.

另外在 Hacker News 上有人整理出來,可以直接理解提案所提出的新格式是什麼:

A somewhat oversimplified summary of the new UUID formats:

UUID6: a timestamp with a weird epoch and 100 ns precision like in UUID1, but in a big-endian order that sorts naturally by time, plus some random bits instead of a predictable MAC address.

UUID7: like UUID6, but uses normal Unix timestamps and allows more timestamp precision.

UUID8: like UUID7, but relaxes requirements on where the timestamp is coming from. Want to use a custom epoch or NTP timestamps or something? UUID8 allows it for the sake of flexibility and future-proofing, but the downside is that there's no standard way to parse the time from one of these -- the time source could be anything monotonic.

這在不同的 storage engine 上面會有不同的討論,這邊先討論 MySQL 系列的 InnoDB,至於 PostgreSQL 的 engine 以及其他資料庫系統,就另外讓更熟悉的人討論了。

InnoDB 採用了 clustered index (可以參考「Database index」這邊的說明),也就是資料本體是以某種定義的大小順序存放。

在 InnoDB 裡面則是用 primary key 的順序來存放資料 (沒有指定 primary key 時會有 fallback 行為),其他的 unique key 與 index key 則是指到 primary key,所以你可以看到 primary key 的大小也會影響到其他的 index key。

所以 128 bits 的 UUID 在大型的 MySQL ecosystem 實在不怎麼受歡迎,在 2010 年的時候 FlickrTwitter 都有發表過 ticket system:「Ticket Servers: Distributed Unique Primary Keys on the Cheap」、「Announcing Snowflake」,兩個系統有不同的需求,但都是產生 64 bits 的 unique id。

其中 Flickr 的系統算是很簡單的,沒有要保證時間順序 (i.e. 先取的號碼一定比較小,以及後取的號碼一定比較大),就用兩台 MySQL 跑 active-active 架構,然後錯開產生的值:

TicketServer1:
auto-increment-increment = 2
auto-increment-offset = 1

TicketServer2:
auto-increment-increment = 2
auto-increment-offset = 2

到現在還是一個蠻簡單的解法...

AWS KMS 推出 Multi-region keys

這應該是 AWS 被許多大客戶敲碗許久的功能之一,AWS KMS 支援 global key:「Encrypt global data client-side with AWS KMS multi-Region keys」。

以前不支援這個功能時,在加密儲存跨區域的資料會有兩種作法,以 us-east-1ap-northeast-1 為例子來說:

第一種是透過 replication 的概念,檔案內容從 us-east-1 解開後,透過 TLS 傳到 ap-northeast-1 再加密,所以不同區的密文內容是不同的。

第二種是自己抽象一層 AES key,檔案內容都用這把 AES key 加解密,而這把 AES key 則透過不同區的 AWS KMS 保護,但這樣做又要自己搞 key rotation,另外還可能會有 auditing 的問題...

現在 AWS KMS 直接支援就省事很多了:

文章裡面是拿 DynamoDB 當範例,不過其他只要能夠用 AWS KMS 應用應該也能用。

GitHub 支援 SSH 使用 Security Key 了

GitHub 宣佈支援使用 security key 的 SSH key 操作了:「Security keys are now supported for SSH Git operations」。

也就是需要 SSH key + security key 才有辦法認證,只有拿到 SSH key 或是 security key 都是沒有辦法認證過。

目前官方支援 ecdsa-sked25519-sk

Now you can use two additional key types: ecdsa-sk and ed25519-sk, where the “sk” suffix is short for “security key.”

不過在 Ubuntu 20.04 下用預設的系統只能支援 ecdsa-sk,因為 ed25519-sk 會遇到類似「ed25519 problem with libressl」這邊的問題,就算你用的是 OpenSSL

然後生完 key 後在 ~/.ssh/config 裡面指定對 github.com 使用這把 key:

Host github.com
    IdentityFile ~/.ssh/id_ecdsa_sk

接下來操作的時候就會需要碰一下 security key 了。

Twitter 的 MFA 可以加入多支 YubiKey 了

我手上有好幾隻 YubiKey,目前幾個有在用的服務都有支援同時綁定多組 U2F/WebAuthn 的能力 (像是 FacebookGitHub)。

Twitter 一開始推出的時候也可以支援多組,但在去年 2020 年八月的時候發現這個功能被拔掉,只能放一把進去。

我自己開了一張 ticket 定時回頭看一下有沒有修正,剛剛定期回顧發現這個功能被加回來了,而且官方的文件上也加上去了:「How to use two-factor authentication」。

翻了一下 Internet Archive 上的資料,看起來是 3/113/16 中間更新文件的...

手上有多把 security key 的人也可以處理一下。

還原被碼掉的 PEM 資訊 (SSH RSA key)

在「Recovering a full PEM Private Key when half of it is redacted」這邊看到的,起因是 _SaxX_ 幫客戶做滲透測試時找到客戶公開在網路上的 SSH key,然後他就碼掉一部分貼出來:

原圖是這樣,接下來就開始被還原 XD

首先是 OCR 的過程,被稱為是整個還原過程最難的一部分 (哭爸啊):

Ironically, this was the hardest part of the challenge. It took the longest time of all the steps and was the easiest to make errors in.

接下來就是解讀 PEM 檔的格式,可以藉此得到裡面的參數。

然後是套公式,窮舉運算裡面的值,可以看到迴圈 kp 只算了 365537,就推算出可能的 p

e = 65537
q = 0xc28871e8714090e0a33327b88acc57eef2eb6033ac6bc44f31baeac33cbc026c3e8bbe9e0f77c8dbc0b4bfed0273f6621d24bc1effc0b6c06427b89758f6d433a02bf996d42e1e2750738ac3b85b4a187a3bcb4124d62296cb0eecaa5b70fb84a12254b0973797a1e53829ec59f22238eab77b211664fc2fa686893dda43756c895953e573fd52aa9bb41d22306135c81174a001b32f5407d4f72d80c5de2850541de5d55c19c1f817eea994dfa534b6d941ba204b306225a9e06ddb048f4e34507540fb3f03efeb30bdd076cfa22b135c9037c9e18fe4fa70cf61cea8c002e9c85e53c1eaac935042d00697270f05b8a7976846963c933dadd527227e6c45e1
dp = 0x878f7c1b9b19b1693c1371305f194cd08c770c8f5976b2d8e3cf769a1117080d6e90a10aef9da6eb5b34219b71f4c8e5cde3a9d36945ac507ee6dfe4c146e7458ef83fa065e3036e5fbf15597e97a7ba93a31124d97c177e68e38adc4c45858417abf8034745d6b3782a195e6dd3cf0be14f5d97247900e9aac3b2b5a89f33a3f8f71d27d670401ca185eb9c88644b7985e4d98a7da37bfffdb737e54b6e0de2004d0c8c425fb16380431d7de40540c02346c98991b748ebbc8aac73dd58de6f7ff00a302f4047020b6cd9098f6ba686994f5e043e7181edfc552e18bce42b3a42b63f7ccb7729b74e76a040055d397278cb939240f236d0a2a79757ba7a9f09

for kp in range(3, e):
    p_mul = dp * e - 1
    if p_mul % kp == 0:
        p = (p_mul // kp) + 1
        if isPrime(p):
            print(f"Possible p: {p}")

後面就是跑驗證確認,就被打出來了...

Akamai 也推出了 Key-Value 服務 EdgeKV

沒介紹過 Akamai 的一些架構,先講到 Akamai 的 Edge 端 Serverless 架構是 EdgeWorkers,跑的是 JavaScript:

EdgeWorkers lets developers just code — integrating into existing CI/CD workflows and enabling multiple teams to work in parallel using JavaScript. EdgeWorkers eliminates the hassle of managing compute resources and building for scale.

然後這次推出的是 EdgeKV,目前還在 Beta 版:「Serverless Storage at the Edge (EdgeKV Beta)」。

如同名字所說的,架構上 Key-Value 架構,放棄了 CAP theorem 裡面的 C,改走 Eventual Consistency:

EdgeKV uses what is known in distributing computing as an eventual consistency model to perform writes and updates. This model achieves high availability with low read latency by propagating data writes globally. The period of time it takes the system to distribute data globally is called the “inconsistency window”.

隔壁 Cloudflare Workers KV 也是 Eventual Consistency (出自「How KV works」這邊):

KV achieves this performance by being eventually-consistent. Changes are immediately visible in the edge location at which they're made, but may take up to 60 seconds to propagate to all other edge locations.

看起來算是補上競爭對手的產品線...

Dehydrated 取得憑證的預設演算法改成 secp384r1

這兩天弄 dehydrated,結果發現 v0.7.0 取得憑證的預設演算法改成 ECCsecp384r1 了:

Using EC secp384r1 as default certificate type

這會導致很多「稍微舊一點」的 client 失效 (瀏覽器與 library),不知道為什麼要預設... 目前避開的方法是強制在 /etc/dehydrated/config 內設定使用 rsa

KEY_ALGO=rsa

剛剛把公司一堆機器改上去,然後把自己的 server 也加一加...