中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Uber為何要放棄Postgres選擇遷移到MySQL

發布時間:2021-09-13 10:36:39 來源:億速云 閱讀:136 作者:柒染 欄目:web開發

Uber為何要放棄Postgres選擇遷移到MySQL,針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。

Uber 的早期架構包含了一個用 Python 開發的單體后端應用程序,這個應用程序使用 Postgres 作為數據存儲。從那個時候開始,Uber 的架構已經發生了巨大變化,變成了微服務,并采用新的數據平臺模型。具體地說,之前使用 Postgres 的地方,現在改用 Schemaless,一種構建在 MySQL 之上的新型數據庫分片層。在本文中,我們將探討 Postgres 的一些缺點,并解釋為什么我們要在 MySQL 之上構建 Schemaless 和其他后端服務。

1. Postgres 架構

我們遭遇了 Postgres 的諸多限制:

  • 低效的寫入操作;

  • 低效的數據復制;

  • 數據損壞問題;

  • 糟糕的副本 MVCC 支持;

  • 難以升級到新版本。

我們將通過分析 Postgres 的表和索引在磁盤上的表示方式來探究以上這些限制,并將其與 MySQL 的 InnoDB 存儲引擎進行比較。請注意,我們的分析主要是基于我們對較舊的 Postgres 9.2 版本系列的經驗。據我們所知,在本文中討論的內部架構在較新的 Postgres 發行版中并未發生顯著變化,并且至少自 Postgres 8.3 發行版(現在已近 10 歲)以來,9.2 版本的基本設計都沒有發生顯著變化。

磁盤表示

一個關系型數據庫必須能夠執行一些關鍵任務:

  • 提供插入、更新和刪除能力;

  • 提供修改模式的能力;

  • 支持 MVCC,讓不同的數據庫連接具有各自的事務視圖。

這些功能如何協同工作是設計數據庫磁盤數據表示的重要部分。

Postgres 的一個核心設計是不可變數據行。這些不可變數據行在 Postgres 中被稱為“元組”。這些元組通過 ctid 來唯一標識。從概念上看,ctid 表示元組在磁盤上的位置(即物理磁盤偏移)。可能會有多個 ctid 描述單個行(例如,為了支持 MVCC,可能存在一個數據行的多個版本,或者一個數據行的舊版本還沒有被 autovacuum 進程回收掉)。元組集合構成一張表。表本身是有索引的,這些索引被組織成某種數據結構(通常是 B 樹),將索引字段映射到 ctid。

通常,這些 ctid 對用戶是透明的,但了解它們的工作原理有助于了解 Postgres 表的磁盤結構。要查看當前行的 ctid,可以在語句中將“ctid”添加到列列表中:

uber@[local] uber=> SELECT ctid, * FROM my_table LIMIT 1;  -[ RECORD 1 ]--------+------------------------------  ctid | (0,1)  ...其他字段...

我們通過一個簡單的用戶表來解釋這個。對于每個用戶,我們都有一個自動遞增的用戶 ID 主鍵、用戶的名字和姓氏以及用戶的出生年份。我們還針對用戶全名(名字和姓氏)定義了復合二級索引,并針對用戶的出生年份定義了另一個二級索引。創建表的 DDL 可能是這樣的:

CREATE TABLE users (  id SERIAL,  first TEXT,  last TEXT,  birth_year INTEGER,  PRIMARY KEY (id)  );  CREATE INDEX ix_users_first_last ON users (first, last);  CREATE INDEX ix_users_birth_year ON users (birth_year);

這里定義了三個索引:一個主鍵索引和兩個二級索引。

我們往表中插入以下這些數據,包括一些有影響力的歷史數學家:

Uber為何要放棄Postgres選擇遷移到MySQL

如前所述,這里的每一行都有一個隱式、唯一的 ctid。因此,我們可以這樣考慮表的內部表示形式:

Uber為何要放棄Postgres選擇遷移到MySQL

主鍵索引(將 id 映射到 ctid)的定義如下:

Uber為何要放棄Postgres選擇遷移到MySQL

B 樹索引是在 id 字段上定義的,并且 B 樹中的每個節點都存有 ctid 的值。請注意,在這種情況下,由于使用了自動遞增的 ID,B 樹中字段的順序恰好與表中的順序相同,但并不是一直都這樣。

二級索引看起來差不多,主要區別在于字段的存儲順序不同,因為 B 樹必須按字典順序來組織。(first,last) 索引從名字的字母表順序開始:

Uber為何要放棄Postgres選擇遷移到MySQL

類似的,birth_year 索引按照升序排列,如下所示:

Uber為何要放棄Postgres選擇遷移到MySQL

對于后兩種情況,二級索引中的 ctid 字段不是按照字典順序遞增的,這與自動遞增主鍵的情況不同。

假設我們需要更新該表中的一條記錄,比如我們要更新 al-Khwārizmī的出生年份。如前所述,行的元組是不可變的。因此,為了更新記錄,我們向表中添加了一個新的元組。這個新的元組有一個新的 ctid,我們將其稱為 I。Postgres 需要區分新元組 I 與舊元組 D。在內部,Postgres 在每個元組中保存了一個版本字段和一個指向先前元組的指針(如果有的話)。因此,表的最新結構如下所示:

Uber為何要放棄Postgres選擇遷移到MySQL

只要存在 al-Khwārizmī行的兩個版本,索引中就必須同時包含兩個行的條目。為簡便起見,我們省略了主鍵索引,只顯示了二級索引,如下所示:

Uber為何要放棄Postgres選擇遷移到MySQL

我們用紅色表示舊數據行,用綠色表示新數據行。Postgres 使用另一個版本字段來確定哪個元組是最新的。數據庫根據這個字段確定哪個元組對不允許查看新版本數據的事務可見。

Uber為何要放棄Postgres選擇遷移到MySQL

在 Postgres 中,主索引和二級索引都直接指向磁盤上的元組偏移量。當元組位置發生變化時,必須更新所有索引。

復制

當我們在表中插入新行時,如果啟用了流式復制,Postgres 需要對其進行復制。為了能夠在發生崩潰后恢復,數據庫維護了預寫日志(WAL),并用它來實現兩階段提交。即使未啟用流式復制,數據庫也必須維護 WAL,因為 WAL 可以保證 ACID 中的原子性和持久性。

為了更好地理解 WAL,我們可以想象一下如果數據庫意外發生崩潰(例如突然斷電)會發生什么。WAL 代表了一系列數據庫計劃對表和索引在磁盤上內容做出的更改。Postgres 守護進程在啟動時會將 WAL 的數據與磁盤上的實際數據進行對比。如果 WAL 中包含未反映到磁盤上的數據,數據庫就會更正元組或索引數據,并回滾出現在 WAL 中但在事務中沒有被提交的數據。

Postgres 通過將主數據庫上的 WAL 發送給副本來實現流式復制。每個副本數據庫就像是在進行崩潰恢復,不斷地應用 WAL 更新。流式復制和實際發生崩潰恢復之間的唯一區別是,處于“熱備用”模式的副本在應用 WAL 時可以提供查詢服務,但真正處于崩潰恢復模式的 Postgres 數據庫通常會拒絕提供查詢服務,直到數據庫實例完成崩潰恢復過程。

因為 WAL 實際上是為實現崩潰恢復而設計的,所以它包含了底層的磁盤更新信息。WAL 包含了元組及其磁盤偏移量(即行 ctid)在磁盤上的表示。如果副本完全與主數據庫同步,此時暫停 Postgres 的主數據庫和副本,那么副本的磁盤內容與主數據庫的磁盤內容將完全一致。因此,如果副本與主數據庫不同步,可以用 rsync 之類的工具來修復。

2. Postgres 的設計所帶來的后果

Postgres 的設計導致 Uber 的數據效率低下,還讓我們遇到了很多麻煩。

寫入放大

Postgres 的第一個問題是寫入放大。通常,寫入放大是指將數據寫入 SSD 磁盤時遇到的問題:小的邏輯更新(例如,寫入幾個字節)在轉換到物理層時會放大,成本會變高。在之前的示例中,如果我們對 al-Khwārizmī的出生年份進行小的邏輯更新,必須進行至少四個物理更新:

  1. 鴻蒙官方戰略合作共建——HarmonyOS技術社區

  2. 將新的行元組寫入表空間;

  3. 更新主鍵索引;

  4. 更新 (first,last) 索引;

  5. 更新 birth_year 索引。

實際上,這四個更新也只反映了對主表空間的寫操作。除此之外,這些寫操作也需要反映在 WAL 中,因此磁盤上的寫操作總數會變得更多。

這里值得注意的是更新 2 和更新 3。在更新 al-Khwārizmī的出生年份時,實際上并沒有修改它的主鍵,也沒有修改名字和姓氏。但盡管如此,仍然必須在數據庫中創建新的行元組,以便更新這些索引。對于具有大量二級索引的表,這些多余的步驟可能會導致效率低下。例如,如果我們在一張表中定義了十二個索引,即使只更新了單個索引對應的字段,也必須將該更新傳播給所有 12 個索引,以便反映新行的 ctid。

復制

這個寫入放大問題自然也轉化到了復制層,因為復制發生在磁盤級別。數據庫并不會復制小的邏輯記錄,例如“將 ctid D 的出生年份更改為 770”,而是將之前的 4 個 WAL 條目傳播到網絡上。因此,寫入放大問題也轉化為復制放大問題,Postgres 復制數據流很快變得非常冗長,可能占用大量帶寬。

如果 Postgres 復制僅發生在單個數據中心內,那么復制帶寬可能就不是問題。現代網絡設備和交換機可以處理大量帶寬,很多托管服務提供商還提供了免費或便宜的數據中心內部帶寬。但是,如果要在數據中心之間進行復制,問題就會迅速升級。例如,Uber 最初使用了西海岸托管中心里的物理服務器。為了進行災備,我們在東海岸托管中心添加了服務器。于是,我們在西部數據中心里有一個主 Postgres 實例(加上副本),在東部也有一個副本集。

級聯復制將數據中心間的帶寬限制為只能滿足主數據庫和單個副本之間的帶寬需求,雖然第二個數據中心里還有很多副本。因為 Postgres 復制協議的冗繁,使用了大量索引的數據庫會有很大的數據量。購買跨地域大帶寬成本非常高昂,即使錢不成問題,也不可能獲得與本地帶寬類似的效果。這個帶寬問題也給 WAL 歸檔帶來了麻煩。除了將所有 WAL 更新從西海岸發送到東海岸之外,我們還要將所有 WAL 都存檔到文件存儲服務中,這是為了確保在發生災難時我們可以還原數據。在早期的流量高峰期間,我們寫入存儲服務的帶寬不夠快,無法跟上 WAL 的寫入速度。

數據損壞

在例行升級主數據庫以便增加數據庫容量的過程中,我們遭遇了 Postgres 9.2 個一個 bug。因為副本在切換時間方面出現了錯誤,導致其中一些副本錯誤地應用了一小部分 WAL 記錄。由于這個問題,一些本應由版本控制機制標記為無效的記錄實際上并未被標記為無效。

下面的查詢說明了這個錯誤將如何影響我們的用戶表:

SELECT * FROM users WHERE id = 4;

這個查詢將返回兩條記錄:初始的 al-Khwārizmī行(出生年份為 780 CE)和新的 al-Khwārizmī行(出生年份為 770 CE)。如果將 ctid 添加到 WHERE 中,對于這兩條返回的記錄,我們將看到不同的 ctid 值。

這個問題非常煩人。首先,我們無法得知這個問題究竟影響了多少行數據。數據庫返回的重復結果在很多情況下會導致應用程序邏輯故障。我們最終添加了防御性編程語句,用來檢測會出現這個問題的表。這個錯誤影響到了所有服務器,而在不同的副本實例上損壞的數據行是不一樣的。也就是說,在其中一個副本實例上,行 X 可能是壞的,行 Y 是好的,但是在另一副本實例上,行 X 可能是好,行 Y 可能是壞的。我們無法確定數據損壞的副本數量以及問題是否影響了主數據庫。

據我們所知,每個數據庫只有幾行數據會出現這個問題,但我們擔心的是,由于復制發生在物理級別,最后可能會完全破壞數據庫索引。B 樹索引很重要的一點是必須定期進行重新平衡(rebalance),并且當子樹移動到新的磁盤位置時,這些重新平衡操作可能會完全改變樹的結構。如果移動了錯誤的數據,則可能導致樹的大部分完全無效。

最后,我們找到了問題所在,并確定新的主數據庫沒有損壞的數據行。我們通過從主數據庫的最新快照重新同步所有副本(這是一個費力的過程)來修復副本的數據損壞問題。

我們遇到的錯誤只出現在 Postgres 9.2 的某些版本中,并且已經修復了很長時間了。但是,我們仍然擔心此類錯誤會再次發生。新版本的 Postgres 可能還會出現此類錯誤,并且由于數據復制的方式,這類問題有可能被傳播到所有的數據庫中。

副本 MVCC

Postgres 沒有提供真正的副本 MVCC 支持。副本只應用 WAL 更新,導致它們在任何時候都具有與主數據庫相同的磁盤數據副本。這種設計給 Uber 帶來了麻煩。

Postgres 需要為 MVCC 維護舊數據的一個副本。如果流式復制遇到一個正在執行的事務,而數據庫更新影響到了事務范圍內的行,那么更新操作就會被阻塞。在這種情況下,Postgres 會暫停 WAL 線程,直到事務結束。如果事務處理要花費很長時間,這就會是個問題,因為副本可能嚴重滯后于主數據庫。因此,Postgres 在這種情況下應用超時策略:如果一個事務導致 WAL 發生阻塞一定的時間,Postgres 將會終止這個事務。

這種設計意味著副本通常會比主數據庫落后幾秒鐘,很容易出現事務被終止的情況。例如,假設開發人員寫了一些代碼,需要通過電子郵件將收據發送給用戶。根據編寫方式的不同,代碼可能會隱式地讓數據庫事務處于打開狀態,直到電子郵件完成發送為止。盡管在執行不相關的阻塞 IO 時一直打開數據庫事務是很糟糕的做法,但大多數工程師并不是數據庫專家,他們可能也不知道有這個問題,特別是在使用隱藏了底層細節的 ORM 框架時。

升級 Postgres

由于復制發生在物理層面,所以我們無法在 Postgres 的不同版本之間復制數據。Postgres 9.3 的主數據庫不能被復制到 Postgres 9.2 的副本,而 Postgres 9.2 的主數據庫也不能被復制到 Postgres 9.3 的副本。

我們按照以下這些步驟從一個 Postgres GA 版本升級到另一個版本:

  • 關閉主數據庫。

  • 在主數據庫上運行 pg_upgrade 命令,這個命令會就地更新主數據庫數據。對于大型數據庫,通常需要花費數小時,并且在這個過程過程中無法從主數據庫讀取數據。

  • 再次啟動主數據庫。

  • 創建主數據庫的最新快照。這一步驟完全復制了主數據庫的所有數據,因此大型數據庫也需要花費數小時。

  • 擦除所有副本,并將最新的快照從主數據庫還原到副本上。

  • 將副本帶回到復制層次結構中。等待副本完全跟上主數據庫的所有更新。

我們從 Postgres 9.1 開始,并成功完成了升級過程,遷移到了 Postgres 9.2。但是,這個過程花費了數小時,我們無力承擔再次執行這種升級過程的費用。到 Postgres 9.3 發布時,Uber 的規模增長極大增加了我們的數據集,因此升級時間就變得更長了。因此,即使 Postgres 9.5 已經發布了,我們的 Postgres 實例仍然是 9.2 版本。

如果你的 Postgres 是 9.4 或更高版本,可以使用 pgologic 之類的東西,它為 Postgres 實現了一個邏輯復制層。你可以用它在不同的 Postgres 版本之間復制數據,這意味著可以從 9.4 升級到 9.5,而不會造成大面積停機。不過,這個功能仍然是有問題的,因為它尚未被集成到 Postgres 主線中。而對于那些使用較舊版本的 Postgres 的人來說,pgologic 并不適用。

3. MySQL 架構

上文解釋了 Postgres 的一些局限性,接下來,我們將解釋為什么 MySQL 會成為 Uber 工程團隊存儲項目(例如 Schemaless)的新工具。在很多情況下,我們發現 MySQL 更適合我們的使用場景。為了理解這些差異,我們研究了 MySQL 的架構,并將其與 Postgres 進行了對比。我們專門分析了 MySQL 的 InnoDB 存儲引擎。

InnoDB 的磁盤表示

與 Postgres 一樣,InnoDB 支持 MVCC 和可變數據等高級功能。關于 InnoDB 磁盤表示的詳盡細節不在本文的討論范圍之內,我們將把重點放在它與 Postgres 的主要區別上。

最主要的架構差異是:Postgres 直接將索引記錄映射到磁盤上的位置,而 InnoDB 使用了二級結構。InnoDB 的二級索引有一個指向主鍵值的指針,而不是指向磁盤位置的指針(如 Postgres 中的 ctid)。因此,MySQL 會將二級索引將索引鍵與主鍵相關聯:

Uber為何要放棄Postgres選擇遷移到MySQL

要基于 (first, last) 索引 執行查詢,需要進行兩次查找。第一次先搜索表,找到記錄的主鍵。在找到主鍵之后,搜索主鍵索引,找到數據行對應的磁盤位置。

所以,在執行二級查找時,InnoDB 相比 Postgres 略有不利,因為 InnoDB 必須搜索兩個索引,而 Postgres 只需要搜索一個。但是,由于數據已經規范化,在更新行數據時只需要更新實際發生變化的索引記錄。此外,InnoDB 通常會在原地進行行數據更新。為了支持 MVCC,如果舊事務需要引用一行數據,MySQL 會將舊行復制到一個叫作回滾段的特殊區域中。

我們來看看更新 al-Khwārizmī的出生年份會發生什么。如果空間足夠,id 為 4 的那一行數據中的出生年份字段會進行原地更新(實際上,這個更新總是發生在原地,因為出生年份是一個占用固定空間量的整數)。出生年份索引也進行原地更新。舊數據行將被復制到回滾段。主鍵索引不需要更新,(first, last) 索引也不需要更新。即使這張表有大量索引,也只需要更新包含 birth_year 字段的索引。假設我們基于 signup_date、last_login_time 等字段建立了索引,我們不需要更新這些索引,但在 Postgres 中需要更新。

這種設計還讓數據清理和壓縮變得更加高效。回滾段中的數據可以直接清除,相比之下,Postgres 的 autovacuum 進程必須進行全表掃描來識別哪些行可以清除。

Uber為何要放棄Postgres選擇遷移到MySQL

MySQL 使用了額外的中間層:二級索引記錄指向主索引記錄,主索引保存了數據行在磁盤上的位置。如果數據行偏移量發生變化,只需要更新主索引。

復制

MySQL 支持多種不同的復制模式:

  • 基于語句的復制將會復制邏輯 SQL 語句(它將按字面意義復制 SQL 語句,例如:UPDATE users SET birth_year = 770 WHERE id = 4);

  • 基于行的復制將會復制發生變化的行記錄;

  • 混合復制將這兩種模式混合在一起。

這幾種模式各有優缺點。基于語句的復制通常是最緊湊的,但可能需要副本應用大量語句來更新少量數據。另一方面,基于行的復制(與 Postgres WAL 復制類似)雖然更為冗繁,但更具可預測性和在副本上的更新效率。

在 MySQL 中,只有主索引有指向行的磁盤偏移量的指針。在進行復制時,這具有重要的意義。MySQL 復制流只需要包含有關行的邏輯更新信息。對于類似“將行 X 的時間戳從 T_1 更改為 T_2”這樣的更新,副本會自動推斷需要修改哪些索引。

相比之下,Postgres 復制流包含了物理變更,例如“在磁盤偏移量 8,382,491 處寫入字節 XYZ”。在使用 Postgres 時,對磁盤進行的每一個物理變更都需要包含在 WAL 流中。較小的邏輯修改(例如更新時間戳)也需要執行很多磁盤變更:Postgres 必須插入新的元組,并更新所有索引,讓它們指向這個元組,所以會有很多變更被放入 WAL 流中。這種設計差異意味著 MySQL 復制二進制日志比 PostgreSQL WAL 流更緊湊。

復制方式也對副本的 MVCC 產生重要影響。由于 MySQL 復制流具有邏輯更新,副本可以具有真正的 MVCC 語義,所以對副本的讀取查詢不會阻塞復制流。相比之下,Postgres WAL 流包含了磁盤上的物理更改,Postgres 副本無法應用與讀取查詢相沖突的復制更新,因此無法實現 MVCC。

MySQL 的復制架構意味著即使有 bug 導致表損壞,也不太可能會發生災難性故障。因為復制發生在邏輯層,所以像重新平衡 B 樹之類的操作永遠不會導致索引損壞。一個典型的 MySQL 復制問題是語句被跳過(或者被應用兩次),這可能導致數據丟失或無效,但不會導致數據庫中斷。

最后,MySQL 的復制架構可以很容易在不同的 MySQL 版本之間進行復制。MySQL 的邏輯復制格式還意味著存儲引擎層中的磁盤變更不會影響復制格式。在進行 MySQL 升級時,典型的做法是一次將更新應用于一個副本,在更新完所有副本后,將其中一個提升為新的主副本。這幾乎可以實現零停機升級,很容易就可以讓 MySQL 保持最新狀態。

4. MySQL 的其他優勢

到目前為止,我們介紹了 Postgres 和 MySQL 的磁盤架構。MySQL 還有其他一些重要方面也讓它的性能明顯優于 Postgres。

緩沖池

首先,兩個數據庫的緩存方式不同。Postgres 為內部緩存分配了一些內存,但是與計算機上的內存總量相比,這些緩存通常很小。為了提高性能,Postgres 允許內核通過頁面緩存自動緩存最近訪問的磁盤數據。例如,我們最大的 Postgres 副本有 768 GB 的可用內存,但實際上只有 25 GB 被用作 Postgres 的進程 RSS 內存,這樣就為 Linux 頁面緩存留出了 700 GB 以上的可用內存。

這種設計的問題在于,與訪問 RSS 內存相比,通過頁面緩存訪問數據實際上開銷更大。為了從磁盤上查找數據,Postgres 進程發出 lseek 和 read 系統調用來定位數據。這些系統調用中的每一個都會引起上下文切換,這比從主存儲器訪問數據的開銷更大。實際上,Postgres 在這方面甚至還沒有完全進行優化:Postgres 并未利用 pread 系統調用,這個系統調用會將 seek 和 read 操作合并為一個系統調用。

相比之下,InnoDB 存儲引擎通過緩沖池實現了自己的 LRU。從邏輯上講,這與 Linux 頁面緩存相似,但它是在用戶空間中實現的。盡管 InnoDB 緩沖池的設計比 Postgres 的設計要復雜得多,但它具備一些優勢:

  1. 鴻蒙官方戰略合作共建——HarmonyOS技術社區

  2. 可以實現自定義 LRU。例如,可以檢測出可能會破壞 LRU 的訪問模式,并防止其造成更大問題。

  3. 較少的上下文切換。通過 InnoDB 緩沖池訪問的數據不需要進行用戶 / 內核上下文切換。最壞的情況是發生 TLB 未命中,這些開銷相對較小,可以通過使用大頁面來緩解。

連接處理

MySQL 通過一個連接一個線程的方式來實現并發連接。這種開銷相對較低,每個線程都有自己的棧內存和分配給特定連接的緩沖堆內存。在 MySQL 中使用 10000 個左右的并發連接,這種情況并不少見,實際上,在我們現有的某些 MySQL 實例上,連接數已經接近這個數字。

但是,Postgres 采用的是一個連接一個進程的設計,這比一個連接一個線程的設計要昂貴得多。派生新進程比生成新線程占用更多的內存。此外,進程之間的 IPC 比線程之間的 IPC 也昂貴得多。Postgres 9.2 通過 System V IPC 原語實現 IPC,而不是使用輕量級的 futex。futex 比 System V IPC 更快,因為通常情況下,futex 不存在竟態條件,因此無需進行上下文切換。

除了內存和 IPC 開銷,Postgres 似乎也無法很好地支持大量連接,即使有足夠的可用內存。我們在 Postgres 中使用數百個活動連接時遇到了大問題。Postgres 文檔建議采用進程外連接池機制來處理大量連接,但沒有詳細說明是為什么。因此,我們使用 pgbouncer 來處理 Postgres 的連接池。但是,我們的后端服務偶爾會出現 bug,導致它們打開的活動連接過多,從而延長了宕機時間。

在 Uber 早期,Postgres 為我們提供了很好的服務,但是隨著公司規模的增長,我們遇到了伸縮性問題。現在,我們仍然保留了一些舊的 Postgres 實例,但大部分數據庫都建立在 MySQL 之上(通常使用 Schemaless 層),或者在某些特殊情況下會使用像 Cassandra 這樣的 NoSQL 數據庫。

關于Uber為何要放棄Postgres選擇遷移到MySQL問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

民丰县| 浙江省| 城口县| 十堰市| 西宁市| 扬中市| 碌曲县| 莆田市| 平乐县| 成安县| 台州市| 新野县| 剑河县| 绿春县| 读书| 张北县| 昌都县| 临沭县| 汉源县| 哈密市| 武威市| 亚东县| 双桥区| 娄底市| 泗水县| 安徽省| 寿阳县| 临潭县| 灵宝市| 北安市| 施甸县| 砀山县| 高雄市| 浦江县| 姚安县| 大连市| 海南省| 天镇县| 苍梧县| 夹江县| 宁河县|