scp -3:直接對兩個 remote host 複製檔案

剛剛找資料才發現的,scp 指令早就可以針對兩個遠端複製檔案了:「scp from one remote server to another remote server」。

可以加上 -3,像是這樣:

scp -3 src:/foo/bar/a.zip dst:/tmp/

不過依照說明可以不用加,因為這是 default 值:

Copies between two remote hosts are transferred through the local host. Without this option the data is copied directly between the two remote hosts. Note that, when using the legacy SCP protocol (via the -O flag), this option selects batch mode for the second host as scp cannot ask for passwords or passphrases for both hosts. This mode is the default.

看了 Stack Exchange 上的回答日期,是 2014 年十月回的,所以至少 Ubuntu 16.04 就有這個功能了?(沒有去查這個功能多早...)

之前一直都是查怎麼用 rsync 搬,然後發現做不到所以都還是傻傻的透過 jump server 轉運檔案,沒想到隔壁棚早就給了解法...

這樣有些情境搬檔案就簡單多了...

Content Defined Chunking (CDC)

前幾個禮拜在 Hacker News Daily 上看到「CDC File Transfer (github.com/google)」這則,連結是指到 GoogleGitHub 專案上,裡面實做了 FastCDC 演算法,另外說明他們為什麼要解這個問題以及對應的成果:「google/cdc-file-transfer」。

Google 的人看起來像是是在 CI/CD 階段遇到頻寬上的問題 (從「The builds are 40-45 GB large.」這邊猜),用 scprsync 看起來都不能解,所以他們自己刻了 FastCDC 演算法來解。

但我對 Content Defined Chunking (CDC) 不熟,所以先查一下 CDC 是什麼東西,就查到 restic 這篇講得很清楚:「Foundation - Introducing Content Defined Chunking (CDC)」。

要計算 delta 很直覺的作法就是要切 chunk,而接著的直覺就是固定大小的 chunk 切開,像是這樣每 16 bytes 切一個 chunk:

0123456789abcdef 0123456789abcdef 0123456789abcdef 0123456789abcdef

如果其中一個地方有變化,但其他沒變化的話就可以透過 cryptographic hash function (像是 SHA-256) 確認 chunk 內容一樣,進而省下很多傳輸的頻寬:

0123456789abcdef 0123456789ABCDEF 0123456789abcdef 0123456789abcdef

但可以馬上看出來這個方法的大缺點是只能處理 replacement,很難處理 insert & delete 的部份,舉例來說,如果變更是在開頭的地方加上 ABC,就會造成 chunk 會完全不一樣,而導致全部都要再傳一次:

ABC0123456789abc def0123456789abc def0123456789abc def0123456789abc def

這邊其實是個經典的演算法問題:想要找出兩個 string 的差異 (把舊的內容當作一個 string,新的內容也當作一個 string)。

這個問題算是 Edit distance 類型的題目,但你會發現解 Edit distance 的演算法會需要先傳輸完整個 string 才能開始跑演算法,這就本末倒置了。

而另外一個想法是,放棄固定的 chunk 大小,改用其他方式決定 chunk 的邊界要切在哪裡。而 CDC 就是利用一段 sliding window + hash 來找出切割的點。

文章裡面提到的 sliding window 是 64 bytes,這邊就可以算出對應的 HASH(b0, b1, ..., b63),然後往右滑動變成 HASH(b1, b2, ..., b64),再來是 HASH(b2, b3, ..., b65),一直往右滑動計算。

接下來 restic 會看 hash 值,如果最低的 21 bits 都是 0 就切開,所以 chunk 大小的期望值應該是 2MB?(這邊不確定,好像不能直接用 2^21 算,應該用積分之類的方法...)

For each fingerprint, restic then tests if the lowest 21 bits are zero. If this is the case, restic found a new chunk boundary.

而這個演算法可以適應新增與刪除的操作,不會造成從新增或刪除後的資料都要重傳,只有自己這個 chunk 需要重傳 (可能前或後的 chunk 也會要)。

然後挑一下 hash function 的特性,就可以讓計算的速度也很快。這邊提到了 hash function 可以用 Rolling hash,可以很快的從 HASH(b0, b1, ..., b63) 算出 HASH(b1, b2, ..., b64),而不需要全部重算。

有了 chunk 後,再用 cryptographic hash function 比較 chunk 的內容是否一樣,這樣就可以大幅降低傳輸所需要的頻寬了。

AWS 流量相關的 Free Tier 增加不少...

Jeff Barr 出來公告增加 AWS 流量相關的 free tier:「AWS Free Tier Data Transfer Expansion – 100 GB From Regions and 1 TB From Amazon CloudFront Per Month」。

一般性的 data transfer 從 1GB/month/region 變成 100GB/mo,現在是 21 regions 所以不會有反例,另外大多數的人或是團隊也就固定用一兩個 region,這個 free tier 大概可以省個 $10 到 $20 左右?

Data Transfer from AWS Regions to the Internet is now free for up to 100 GB of data per month (up from 1 GB per region). This includes Amazon EC2, Amazon S3, Elastic Load Balancing, and so forth. The expansion does not apply to the AWS GovCloud or AWS China Regions.

另外是 CloudFront 的部份,本來只有前 12 個月有 free tier,現在是開放到所有帳號都有,另外從 50GB/month 升到 1TB/month,這個部份的 free tier 就不少了,大概是 $100 到 $200?

Data Transfer from Amazon CloudFront is now free for up to 1 TB of data per month (up from 50 GB), and is no longer limited to the first 12 months after signup. We are also raising the number of free HTTP and HTTPS requests from 2,000,000 to 10,000,000, and removing the 12 month limit on the 2,000,000 free CloudFront Function invocations per month. The expansion does not apply to data transfer from CloudFront PoPs in China.

今年十二月才生效,要注意一下不要現在就用爽爽:

This change is effective December 1, 2021 and takes effect with no effort on your part.

這樣好像可以考慮把 blog 與 wiki 都放上去玩玩看,目前這兩個服務都是用 Cloudflare 的 free tier,HiNet 用戶基本上都是連去 Cloudflare 的美西 PoP,偶而離峰時間會用亞洲的點,但都不會是台灣的 PoP...

不過記得之前 WordPress + CloudFront 有些狀況,再研究看看要怎麼弄好了...

OpenSSH 的 scp 改用 SFTP 協定

在「By default, scp(1) now uses SFTP protocol」這邊看到的,OpenSSH 的 scp 改用 SFTP 協定了,原因也有附在文章裡:

SFTP offers more predictable filename handling and does not require expansion of glob(3) patterns via the shell on the remote side.

要注意這是 BC-break change,有些之前會動的 case 在改用 SFTP 後會爛掉,但這算是前進了一大步,scp 因為 spec 的關係很難維護安全性。

在「Deprecating scp」這邊也有提到相關的問題,另外也給出了一些範例。

rsync 的預設值是傳整個檔案,不是 delta

剛好最近工作上需要透過 4G 網路傳大檔案,但希望大檔案傳到一半斷掉後可以續傳,而不要浪費頻寬整個重傳,所以查了資料並且測了一些東西...

其中一個比較特別的是發現 rsync 的預設是傳整個檔案 (當檔案有變化時),而不是傳 delta (有變更的部份),不過還好,可以透過指令強制使用 delta。

在「Does rsync --inplace write to the entire file, or just to the parts that need to be updated? (for btrfs+rsync backups)」這邊有提到幾個需要設定的指令。

首先是標題就有提到的 --inplace,在 manpage 裡面有提到是直接更新檔案,而非建立一個新檔案再 rename,這樣做的缺點是其他的應用程式可能會讀到改到一半的檔案:

update destination files in-place

另外一個提到的是 --no-whole-file,這個要看 --whole-file 的說明來理解,後者就是不開 delta:

copy files whole (w/o delta-xfer algorithm)

第三個是 -c,強制使用 checksum 比對:

skip based on checksum, not mod-time & size

不過我的應用裡面不太想管這個,就沒設定 -c 了,基本上是靠 ssh 的保護,不會有收到錯誤封包的問題。

整體來說,這個方法對兩邊的機器都比較吃資源,而且會遇到應用程式在還在傳輸時讀到檔案的問題,但如果可以克服,而且目標是省頻寬的話,算是個還不錯的方法...

Percona XtraDB Cluster (PXC) 節點離開太久後的惡搞法

Percona 的「How To Recover Percona XtraDB Cluster 5.7 Node Without SST」這邊看到的技巧,不過只能用在 5.7 版,不能用在 8.0 版。我猜這個方法也可以用在其他跑 Galera Cluster 的資料庫上...

維護一組 Percona XtraDB Cluster 時一個常見的問題是,當節點離線太久後有機會無法用 IST (Incremental State Transfer) 跟回來,也就是只要把先前還沒有同步的部份更新進資料庫的方法,這時候就會需要用 SST (State Snapshot Transfer),變成抓整個 full copy。

作者提出來的方法是基於 IST 的大小通常比較小,但 binlog 通常都留蠻久的,所以可以利用 binlog 來幫 IST。

方法是先把 Galara Cluster 關掉,用 MySQL 傳統的 replication 同步到一定程度後,再把 IST 相關的位置設定指到已經同步的位置,接著再把 Galara Cluster 接上去就可以恢復了。

這個方法是 5.7 版限定,因為 8.0 的年代沒辦法改 Galara Cluster 的 wsrep 位置資訊:

Unfortunately, a similar solution does not work with Percona XtraDB Cluster 8.0.x, due to the modified way wsrep positions are kept in the storage engine, hence the trick with updating grastate.dat does not work as expected there.

我覺得可能 Percona 之後會弄出 patch 讓使用者可以改...

EFS 上可以掛 AWS Transfer Family 了

先前 AWS Transfer Family 的後端只能是 Amazon S3,現在則是宣佈可以掛 Amazon EFS 了:「New – AWS Transfer Family support for Amazon Elastic File System」。

EFS 跟 S3 都是沒有空間限制,但 EFS 可以直接在系統上掛起來當作一般的檔案系統用,基本上就是更方便,不過代價就是單位儲存成本貴不少...

這次支援 EFS 對於一些量不大的處理又方便不少,也就是處理完後的檔案另外丟,而上傳上來的檔案可以砍掉的... 如果是上傳上來的檔案需要保留的,用 S3 會比較適合。

透過 WebRTC 直接在網頁對傳檔案的服務

Twitter 上看到的服務 WEBWORMHOLE

透過 WebRTC 直接網頁對網頁傳資料,就不需要再透過第三方服務了。當然這樣做的前提是雙方都要在線上。

另外也可以在 cli 下面用:

之後要傳大檔案找不到空間放的時候可以用看看...

省頻寬的方法:終極版本...

看到「Three ways to reduce the costs of your HTTP(S) API on AWS」這邊介紹在 AWS 上省頻寬費用的方法,看了只能一直笑 XD

第一個是降低 HTTP response 裡沒有用到的 header,因為每天有五十億個 HTTP request,所以只要省 1byte 就是省下 USD$0.25/day:

Since we would send this five billion times per day, every byte we could shave off would save five gigabytes of outgoing data, for a saving of 25 cents per day per byte removed.

然後調了一些參數後省下 USD$1,500/month:

Sending 109 bytes instead of 333 means saving $56 per day, or a bit over $1,500 per month.

第二個是想辦法在 TLS 這邊下手,一開始其中一個方向是利用 TLS session resumption 降低第二次連線的成本,但他們發現沒有什麼參數可以調整:

One thing that reduces handshake transfer size is TLS session resumption. Basically, when a client connects to the service for the second time, it can ask the server to resume the previous TLS session instead of starting a new one, meaning that it doesn’t have to send the certificate again. By looking at access logs, we found that 11% of requests were using a reused TLS session. However, we have a very diverse set of clients that we don’t have much control over, and we also couldn’t find any settings for the AWS Application Load Balancer for session cache size or similar, so there isn’t really anything we can do to affect this.

所以改成把 idle 時間拉長 (避免重新連線):

That leaves reducing the number of handshakes required by reducing the number of connections that the clients need to establish. The default setting for AWS load balancers is to close idle connections after 60 seconds, but it seems to be beneficial to raise this to 10 minutes. This reduced data transfer costs by an additional 8%.

再來是 AWS 本身發的 SSL certification 太肥,所以他們換成 DigiCert 發的,大幅降低憑證本身的大小,反而省下 USD$200/day:

So given that the clients establish approximately two billion connections per day, we’d expect to save four terabytes of outgoing data every day. The actual savings were closer to three terabytes, but this still reduced data transfer costs for a typical day by almost $200.

這些方法真的是頗有趣的 XDDD

不過這些方法也是在想辦法壓榨降低與 client 之間的傳輸量啦,比起成本來說反而是提昇網路反應速度...