ホームページ データベース mysql チュートリアル 怎样解决MySQL数据库主从复制延迟的问题

怎样解决MySQL数据库主从复制延迟的问题

Jun 07, 2016 pm 03:07 PM
mysql コピー 遅れ どうやって データベース 解決する 質問

像 Facebook 、 开心001 、 人人网 、 优酷 、 豆瓣 、 淘宝 等高流量、高并发的网站,单点数据库很难支撑得住,WEB2.0类型的网站中使用MySQL的居多,要么用MySQL自带的 MySQL NDB Cluster (MySQL5.0及以上版本支持MySQL NDB Cluster功能),或者用MySQL自带

Facebook开心001人人网优酷豆瓣淘宝等高流量、高并发的网站,单点数据库很难支撑得住,WEB2.0类型的网站中使用MySQL的居多,要么用MySQL自带的MySQL NDB Cluster(MySQL5.0及以上版本支持MySQL NDB Cluster功能),或者用MySQL自带的分区功能(MySQL5.1及以上版本支持分区功能),我所知道的使用这两种方案的很少,一般使用主从复制,再加上MySQL Proxy实现负载均衡、读写分离等功能,在使用主从复制的基础上,再使用垂直切分及水平切分;或者不使用主从复制,完全使用垂直切分加上水平切分再加上类似Memcached的系统也可以解决问题。

1.优酷的经验
数据库采用水平扩展,主从复制,随着从数据库的增多,复制延迟越来越厉害,最终无法忍受。
最终还是采用数据库的sharding,把一组用户相关的表和数据放到一组数据库上。
使用SSD来优化mysql的I/O,性能提升明显,每块16G,6块SSD做RAID。
数据库的类型选用MYISAM
数据库的拆分策略,先纵向按照业务或者模块拆分。对于一些特别大的表,再采用垂直拆分
根据用户进行分片,尽可能不要跨篇查询。如果确实要跨片查询,可以考虑搜索的方案,先索引再搜索。
分布式的数据库方案太复杂,否掉。

优酷使用的是数据库分片技术,而抛弃了由于数据量的越来越多导致复制延迟的问题。按照user_id进行分片,这样必须有一个全局的表来管理用户与shard的关系,根据user_id可以得到share_id,然后根据share_id去指定的分片查询指定的数据。

假如此表的表名为sharding_manager,如果网站的用户数太多,比如千万级的或甚至更大比如亿级的用户,此时此表也许也会成为一个瓶颈,因为查询会非常频繁,所有的动态请求都要读此表,这时可以用其它的解决方案,比如用Memcached、Tokyo Cabinet、Berkeley DB或其它的性能更高的方案来解决。

具体怎么定位到哪台db服务器,定位到哪个数据库,定位到哪个shard(就是userN,msgN,videoN),优酷网的架构文档中说得不是很仔细,这里只能猜测一下了。

根据优酷的架构图,一共有2台db服务器,每台db服务器有2个数据库,每个数据库有3个shard,这样一共是2 * 2 * 3 = 12个shard。

user_id一般是自增型字段,用户注册的时候可以自动生成,然后看有几台db服务器,假如有m台db服务器,则用 user_id % m便可以分配一台db服务器(例如0对应100,1对应101,以此类推,字段mysql_server_ip的值确定),假设每台服务器有n个数据库,则用user_id % n可以定位到哪个数据库(字段database_name的值确定),假设每个数据库有i个shard,则用user_id % i可以定位到哪个shard(字段shard_id的值确定),这样就可以进行具体的数据库操作了。

user_id share_id mysql_server_ip database_name
101      2           192.168.1.100   shard_db1
105      0           192.168.1.100   shard_db2
108      0           192.168.1.101   shard_db3(或shard_db1)
110      1           192.168.1.101   shard_db4(或shard_db2)

如上述user_id为101的用户,连接数据库服务器192.168.1.100,使用其中的数据库为shard_db1,使用其中的表系列为user2,msg2,video2

如果上述的m,n,i发生变化,比如网站的用户不断增长,需要增加db服务器,此时则需要进行数据库迁移,关于迁移,参见这儿

因为表位于不同的数据库中,所以不同的数据库中表名可以相同
server1(192.168.1.100)
shard_db1
user0
msg0
video0
user1
msg1
video1
...
userN
msgN
videoN
shard_db2
user0
msg0
video0
user1
msg1
video1
...
userN
msgN
videoN

因为表位于不同的数据库服务器中,所以不同的数据库服务器中的数据库名可以相同
server2(192.168.1.101)
shard_db3
(这里也可以用shard_db1)
user0
msg0
video0
user1
msg1
video1
...
userN
msgN
videoN
shard_db4(这里也可以用shard_db2)
user0
msg0
video0
user1
msg1
video1
...
userN
msgN
videoN

2.豆瓣的经验
由于从主库到辅库的复制需要时间
更新主库后,下一个请求往往就是要读数据(更新数据后刷新页面)
从辅库读会导致cache里存放的是旧数据(不知道这个cache具体指的是什么,如果是Memcached的话,如果更新的数据的量很大,难道把所有更新过的数据都保存在Memcached里面吗?)
解决方法:更新数据库后,在预期可能会马上用到的情况下,主动刷新缓存
不完美,but it works

豆瓣后来改为双MySQL Master+Slave说是能解决Replication Delay的问题,不知道是怎么解决的,具体不太清楚。

3.Facebook的经验

下面一段内容引用自www.dbanotes.net
大量的 MySQL + Memcached 服务器,布署简示:
California (主 Write/Read)............. Virginia (Read Only)
主数据中心在 California ,远程中心在 Virginia 。这两个中心网络延迟就有 70ms,MySQL 数据复制延迟有的时候会达到 20ms. 如果要让只读的信息从 Virginia 端发起,Memcached 的 Cache 数据一致性就是个问题。

1 用户发起更新操作,更名 "Jason" 到 "Monkey" ;
2 主数据库写入 "Monkey",删除主端 Memcached 中的名字值,但Virginia 端 Memcached 不删;(这地方在 SQL 解析上作了一点手脚,把更新的操作"示意"给远程);
3 在 Virginia 有人查看该用户 Profile ;
4 在 Memcached 中找到键值,返回值 "Jason";
5 复制追上更新 Slave 数据库用户名字为 "Monkey",删除 Virginia Memcached 中的键值;
6 在 Virginia 有人查看该用户 Profile ;
7 Memcache 中没找到键值,所以从 Slave 中读取,然后得到正确的 "Monkey" 。
Via

从上面3可以看出,也仍然存在数据延迟的问题。同时master中数据库更新的时候不更新slave中的memcached,只是给slave发个通知,说数据已经改变了。

那是不是可以这样,当主服务器有数据更新时,立即更新从服务器中的Memcached中的数据,这样即使有延迟,但延迟的时间应该更短了,基本上可以忽略不计了。

4.Netlog的经验

对于比较重要且必须实时的数据,比如用户刚换密码(密码写入 Master),然后用新密码登录(从 Slaves 读取密码),会造成密码不一致,导致用户短时间内登录出错。所以在这种需要读取实时数据的时候最好从 Master 直接读取,避免 Slaves 数据滞后现象发生。还好,需要读取实时数据的时候不多,比如用户更改了邮件地址,就没必要马上读取,所以这种 Master-Slaves 架构在多数情况下还是有效的。Via这篇文章


このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

MySQL:初心者向けのデータ管理の容易さ MySQL:初心者向けのデータ管理の容易さ Apr 09, 2025 am 12:07 AM

MySQLは、インストールが簡単で、強力で管理しやすいため、初心者に適しています。 1.さまざまなオペレーティングシステムに適した、単純なインストールと構成。 2。データベースとテーブルの作成、挿入、クエリ、更新、削除などの基本操作をサポートします。 3.参加オペレーションやサブクエリなどの高度な機能を提供します。 4.インデックス、クエリの最適化、テーブルパーティション化により、パフォーマンスを改善できます。 5。データのセキュリティと一貫性を確保するために、バックアップ、リカバリ、セキュリティ対策をサポートします。

NAVICATでデータベースパスワードを取得できますか? NAVICATでデータベースパスワードを取得できますか? Apr 08, 2025 pm 09:51 PM

NAVICAT自体はデータベースパスワードを保存せず、暗号化されたパスワードのみを取得できます。解決策:1。パスワードマネージャーを確認します。 2。NAVICATの「パスワードを記憶する」機能を確認します。 3.データベースパスワードをリセットします。 4.データベース管理者に連絡してください。

Navicatプレミアムの作成方法 Navicatプレミアムの作成方法 Apr 09, 2025 am 07:09 AM

NAVICATプレミアムを使用してデータベースを作成します。データベースサーバーに接続し、接続パラメーターを入力します。サーバーを右クリックして、[データベースの作成]を選択します。新しいデータベースの名前と指定された文字セットと照合を入力します。新しいデータベースに接続し、オブジェクトブラウザにテーブルを作成します。テーブルを右クリックして、データを挿入してデータを挿入します。

MariadBのNAVICATでデータベースパスワードを表示する方法は? MariadBのNAVICATでデータベースパスワードを表示する方法は? Apr 08, 2025 pm 09:18 PM

Passwordが暗号化された形式で保存されているため、MariadbのNavicatはデータベースパスワードを直接表示できません。データベースのセキュリティを確保するには、パスワードをリセットするには3つの方法があります。NAVICATを介してパスワードをリセットし、複雑なパスワードを設定します。構成ファイルを表示します(推奨されていない、高リスク)。システムコマンドラインツールを使用します(推奨されません。コマンドラインツールに習熟する必要があります)。

MySQL:簡単な学習のためのシンプルな概念 MySQL:簡単な学習のためのシンプルな概念 Apr 10, 2025 am 09:29 AM

MySQLは、オープンソースのリレーショナルデータベース管理システムです。 1)データベースとテーブルの作成:createdatabaseおよびcreateTableコマンドを使用します。 2)基本操作:挿入、更新、削除、選択。 3)高度な操作:参加、サブクエリ、トランザクション処理。 4)デバッグスキル:構文、データ型、およびアクセス許可を確認します。 5)最適化の提案:インデックスを使用し、選択*を避け、トランザクションを使用します。

NAVICATは、MySQL/Mariadb/PostgreSQLおよびその他のデータベースに接続できません NAVICATは、MySQL/Mariadb/PostgreSQLおよびその他のデータベースに接続できません Apr 08, 2025 pm 11:00 PM

NAVICATがデータベースとそのソリューションに接続できない一般的な理由:1。サーバーの実行ステータスを確認します。 2。接続情報を確認します。 3.ファイアウォール設定を調整します。 4.リモートアクセスを構成します。 5.ネットワークの問題のトラブルシューティング。 6.許可を確認します。 7.バージョンの互換性を確保します。 8。他の可能性のトラブルシューティング。

NAVICATでSQLを実行する方法 NAVICATでSQLを実行する方法 Apr 08, 2025 pm 11:42 PM

NAVICATでSQLを実行する手順:データベースに接続します。 SQLエディターウィンドウを作成します。 SQLクエリまたはスクリプトを書きます。 [実行]ボタンをクリックして、クエリまたはスクリプトを実行します。結果を表示します(クエリが実行された場合)。

NavicatでMySQLへの新しい接続を作成する方法 NavicatでMySQLへの新しい接続を作成する方法 Apr 09, 2025 am 07:21 AM

手順に従って、NAVICATで新しいMySQL接続を作成できます。アプリケーションを開き、新しい接続(CTRL N)を選択します。接続タイプとして「mysql」を選択します。ホスト名/IPアドレス、ポート、ユーザー名、およびパスワードを入力します。 (オプション)Advanced Optionsを構成します。接続を保存して、接続名を入力します。

See all articles