learn.lianglianglee.com/专栏/MySQL实战宝典/00 开篇词 从业务出发,开启海量 MySQL 架构设计.md.html
2022-05-11 18:52:13 +08:00

733 lines
20 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<!-- saved from url=(0046)https://kaiiiz.github.io/hexo-theme-book-demo/ -->
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no">
<link rel="icon" href="/static/favicon.png">
<title>00 开篇词 从业务出发,开启海量 MySQL 架构设计.md.html</title>
<!-- Spectre.css framework -->
<link rel="stylesheet" href="/static/index.css">
<!-- theme css & js -->
<meta name="generator" content="Hexo 4.2.0">
</head>
<body>
<div class="book-container">
<div class="book-sidebar">
<div class="book-brand">
<a href="/">
<img src="/static/favicon.png">
<span>技术文章摘抄</span>
</a>
</div>
<div class="book-menu uncollapsible">
<ul class="uncollapsible">
<li><a href="/" class="current-tab">首页</a></li>
</ul>
<ul class="uncollapsible">
<li><a href="../">上一级</a></li>
</ul>
<ul class="uncollapsible">
<li>
<a class="current-tab" href="/专栏/MySQL实战宝典/00 开篇词 从业务出发,开启海量 MySQL 架构设计.md">00 开篇词 从业务出发,开启海量 MySQL 架构设计.md.html</a>
</li>
<li>
<a href="/专栏/MySQL实战宝典/01 数字类型:避免自增踩坑.md">01 数字类型:避免自增踩坑.md.html</a>
</li>
<li>
<a href="/专栏/MySQL实战宝典/02 字符串类型:不能忽略的 COLLATION.md">02 字符串类型:不能忽略的 COLLATION.md.html</a>
</li>
<li>
<a href="/专栏/MySQL实战宝典/03 日期类型TIMESTAMP 可能是巨坑.md">03 日期类型TIMESTAMP 可能是巨坑.md.html</a>
</li>
<li>
<a href="/专栏/MySQL实战宝典/04 非结构存储:用好 JSON 这张牌.md">04 非结构存储:用好 JSON 这张牌.md.html</a>
</li>
<li>
<a href="/专栏/MySQL实战宝典/05 表结构设计:忘记范式准则.md">05 表结构设计:忘记范式准则.md.html</a>
</li>
<li>
<a href="/专栏/MySQL实战宝典/06 表压缩:不仅仅是空间压缩.md">06 表压缩:不仅仅是空间压缩.md.html</a>
</li>
<li>
<a href="/专栏/MySQL实战宝典/07 表的访问设计:你该选择 SQL 还是 NoSQL.md">07 表的访问设计:你该选择 SQL 还是 NoSQL.md.html</a>
</li>
<li>
<a href="/专栏/MySQL实战宝典/08 索引:排序的艺术.md">08 索引:排序的艺术.md.html</a>
</li>
<li>
<a href="/专栏/MySQL实战宝典/09 索引组织表:万物皆索引.md">09 索引组织表:万物皆索引.md.html</a>
</li>
<li>
<a href="/专栏/MySQL实战宝典/10 组合索引:用好,性能提升 10 倍!.md">10 组合索引:用好,性能提升 10 倍!.md.html</a>
</li>
<li>
<a href="/专栏/MySQL实战宝典/11 索引出错:请理解 CBO 的工作原理.md">11 索引出错:请理解 CBO 的工作原理.md.html</a>
</li>
<li>
<a href="/专栏/MySQL实战宝典/12 JOIN 连接:到底能不能写 JOIN.md">12 JOIN 连接:到底能不能写 JOIN.md.html</a>
</li>
<li>
<a href="/专栏/MySQL实战宝典/13 子查询:放心地使用子查询功能吧!.md">13 子查询:放心地使用子查询功能吧!.md.html</a>
</li>
<li>
<a href="/专栏/MySQL实战宝典/14 分区表:哪些场景我不建议用分区表?.md">14 分区表:哪些场景我不建议用分区表?.md.html</a>
</li>
<li>
<a href="/专栏/MySQL实战宝典/15 MySQL 复制:最简单也最容易配置出错.md">15 MySQL 复制:最简单也最容易配置出错.md.html</a>
</li>
<li>
<a href="/专栏/MySQL实战宝典/16 读写分离设计:复制延迟?其实是你用错了.md">16 读写分离设计:复制延迟?其实是你用错了.md.html</a>
</li>
<li>
<a href="/专栏/MySQL实战宝典/17 高可用设计:你怎么活用三大架构方案?.md">17 高可用设计:你怎么活用三大架构方案?.md.html</a>
</li>
<li>
<a href="/专栏/MySQL实战宝典/18 金融级高可用架构:必不可少的数据核对.md">18 金融级高可用架构:必不可少的数据核对.md.html</a>
</li>
<li>
<a href="/专栏/MySQL实战宝典/19 高可用套件:选择这么多,你该如何选?.md">19 高可用套件:选择这么多,你该如何选?.md.html</a>
</li>
<li>
<a href="/专栏/MySQL实战宝典/20 InnoDB Cluster改变历史的新产品.md">20 InnoDB Cluster改变历史的新产品.md.html</a>
</li>
<li>
<a href="/专栏/MySQL实战宝典/21 数据库备份:备份文件也要检查!.md">21 数据库备份:备份文件也要检查!.md.html</a>
</li>
<li>
<a href="/专栏/MySQL实战宝典/22 分布式数据库架构:彻底理解什么叫分布式数据库.md">22 分布式数据库架构:彻底理解什么叫分布式数据库.md.html</a>
</li>
<li>
<a href="/专栏/MySQL实战宝典/23 分布式数据库表结构设计:如何正确地将数据分片?.md">23 分布式数据库表结构设计:如何正确地将数据分片?.md.html</a>
</li>
<li>
<a href="/专栏/MySQL实战宝典/24 分布式数据库索引设计:二级索引、全局索引的最佳设计实践.md">24 分布式数据库索引设计:二级索引、全局索引的最佳设计实践.md.html</a>
</li>
<li>
<a href="/专栏/MySQL实战宝典/25 分布式数据库架构选型:分库分表 or 中间件 .md">25 分布式数据库架构选型:分库分表 or 中间件 .md.html</a>
</li>
<li>
<a href="/专栏/MySQL实战宝典/26 分布式设计之禅:全链路的条带化设计.md">26 分布式设计之禅:全链路的条带化设计.md.html</a>
</li>
<li>
<a href="/专栏/MySQL实战宝典/27 分布式事务:我们到底要不要使用 2PC.md">27 分布式事务:我们到底要不要使用 2PC.md.html</a>
</li>
</ul>
</div>
</div>
<div class="sidebar-toggle" onclick="sidebar_toggle()" onmouseover="add_inner()" onmouseleave="remove_inner()">
<div class="sidebar-toggle-inner"></div>
</div>
<script>
function add_inner() {
let inner = document.querySelector('.sidebar-toggle-inner')
inner.classList.add('show')
}
function remove_inner() {
let inner = document.querySelector('.sidebar-toggle-inner')
inner.classList.remove('show')
}
function sidebar_toggle() {
let sidebar_toggle = document.querySelector('.sidebar-toggle')
let sidebar = document.querySelector('.book-sidebar')
let content = document.querySelector('.off-canvas-content')
if (sidebar_toggle.classList.contains('extend')) { // show
sidebar_toggle.classList.remove('extend')
sidebar.classList.remove('hide')
content.classList.remove('extend')
} else { // hide
sidebar_toggle.classList.add('extend')
sidebar.classList.add('hide')
content.classList.add('extend')
}
}
function open_sidebar() {
let sidebar = document.querySelector('.book-sidebar')
let overlay = document.querySelector('.off-canvas-overlay')
sidebar.classList.add('show')
overlay.classList.add('show')
}
function hide_canvas() {
let sidebar = document.querySelector('.book-sidebar')
let overlay = document.querySelector('.off-canvas-overlay')
sidebar.classList.remove('show')
overlay.classList.remove('show')
}
</script>
<div class="off-canvas-content">
<div class="columns">
<div class="column col-12 col-lg-12">
<div class="book-navbar">
<!-- For Responsive Layout -->
<header class="navbar">
<section class="navbar-section">
<a onclick="open_sidebar()">
<i class="icon icon-menu"></i>
</a>
</section>
</header>
</div>
<div class="book-content" style="max-width: 960px; margin: 0 auto;
overflow-x: auto;
overflow-y: hidden;">
<div class="book-post">
<p id="tip" align="center"></p>
<div><h1>00 开篇词 从业务出发,开启海量 MySQL 架构设计</h1>
<p>你好我是姜承尧常用ID破产码农目前是腾讯金融数据平台与研发中心总监。</p>
<p>我与 MySQL 结缘已有十余年,最开始在久游开启了数据库职业生涯,接着在网易负责数据库内核、云数据库开发,现在腾讯负责金融支付系统的数据库开发。</p>
<p>毕业至今,我一直从事 MySQL 相关的工作(比如运维、平台开发、内核开发、云计算开发),经历了无数个 DBA 必经的通宵之旅,也因此累积了无数架构实战经验。</p>
<h3>我与 MySQL 相伴相随</h3>
<p>在久游工作时,我负责全国最为热火的网游劲舞团,那时只要说你是负责劲舞团的 DBA身上都闪着光芒但谁又能想到我曾遇到过连续 72 小时的加班回档全服游戏数据。为了避免再次发生类似情况,<strong>早在 2008 年我就在久游设计了多实例高可用架构</strong>,并结合 LVM 快照功能,防止下一次游戏升级可能导致的业务数据错乱等情况。</p>
<p>我可以说是<strong>国内最早从事 MySQL 内核工作的 DBA</strong>。那时随着海量数据的不断发展,业务对于 MySQL 数据库的要求变得更为“苛刻”,不但要能够使用 MySQL还要能对内核进行额外的开发。为此我深入 MySQL 内核设计领域,为迎合 SSD 技术的发展,独立开发了 SBPSecondary Buffer Pool架构并在久游、网易等业务中大规模使用。</p>
<p>在网易期间,我发现 MySQL 数据半同步复制功能不断改进,当时就预见它将很快进入金融核心业务领域,于是<strong>主导网易开源 MySQL 分支版本 InnoSQL设计并开发出金融级 MySQL 高可用架构 VSRVSR 同时作为开源数据库组件,成功应用于某四大行核心系统</strong></p>
<p>2017 年来到腾讯后,我<strong>主导了新一代腾讯金融核心数据库架构的设计与研发</strong>工作,让各位小伙伴所使用的金融与支付功能得到了更为安全的保障。</p>
<p><strong>可以说MySQL 数据库在互联网业务中的成功,让我获益良多:</strong></p>
<ul>
<li>收入不断攀升比起其他种类数据库MySQL 收入显然优势突出。目前,一线城市的数据库从业人员要达到 50 万是很轻松的一件事情,若去互联网公司,薪资可以说上不封顶。</li>
<li>作为一份职业的成就感MySQL 带给我太多的“感动”。伴随着互联网的崛起MySQL 已经成为互联网公司数据库的标准配置。看到自己运维开发的数据库能够支撑数以万计的用户,这种感觉真的是好极了。</li>
</ul>
<p>我时常思考,如何将自己这么多年在 MySQL 方面的知识沉淀形成方法论进行输出,<strong>希望能有更多的同学享受到 MySQL 发展的红利。</strong></p>
<h3>怎么用好 MySQL 呢</h3>
<p>虽然这些年先后出版过 <strong>《MySQL技术内幕》《MySQL内核》</strong> 系列三本书,但相对理论,每本书的方向都较为专一,未能有效地<strong>从整个业务的全链路角度去分享一个互联网海量 MySQL 架构的实现</strong></p>
<p>同样,纵观整个业界,各技术书籍也好,在线课程也罢,都只专注于怎么用好 MySQL 的某一个功能,并没有<strong>站在业务的角度去考虑,怎么设计一个海量并发业务的 MySQL 数据库架构</strong></p>
<blockquote>
<p>比如,站在理论角度看,自增的 INT 类型用于主键没有问题,但站在类似双 11、春节红包的业务角度看INT 类型做核心业务主键非常不可取,甚至会带来无尽的麻烦。</p>
<p>再比如你肯定知道用MySQL 复制技术可以搭建一个高可用架构,但结合不同业务类型,一定要数据库层去完成高可用的架构吗?不一定!因为数据库是有状态的,当发生问题时,切换速度可能比较慢,你其实可以通过与业务相结合的方法去设计一套高可用的架构。</p>
</blockquote>
<p>总之,数据库学到最后,要与业务紧密结合,站在业务的角度,全流程地进行思考,这样才能设计出真正好用的数据库架构。</p>
<p>非常有幸,收到拉勾教育平台的邀请,给了我再次进行 MySQL 创作的动力,拉勾网上有许多技术同学,他们有着一颗对知识渴望的心,希望学习对其工作真正有帮助的课程。</p>
<p>所以我将着力打造好这门课程,结合现阶段你学习 MySQL 时存在的痛点,<strong>如对于 MySQL 8.0 新特性与业务结合、金融级数据库高可用设计、分布式架构设计能力等,</strong> 用自己超过 15 年的一线 MySQL 工作经验,帮助你从业务全流程的角度看待数据库系统,设计出一个基于 MySQL 的海量并发系统。同时,也希望你能在学完这门课程后,形成自己的数据库架构方法论,并积极交流与探讨,不断成长。</p>
<h3>课程设计</h3>
<p>总的来说,我通过表结构设计、索引设计、高可用架构设计、分布式架构设计,由浅入深、循序渐进地与你一起<strong>打造出一个能支撑海量的并发访问的分布式 MySQL 架构。</strong></p>
<p><strong>模块一:表结构设计</strong>,该模块中我会以实际的业务为案例分析,先带你分析不同字段类型的选型,然后再学习 MySQL 中表的设计,比如表结构设计、访问设计、物理存储设计。通过模块一解决你表结构设计的痛点问题,让你打好架构设计最为基础的工作。</p>
<p>又因为单表的设计不足以支撑业务上线,所以在学完“表结构设计”后,<strong>模块二就是索引的设计</strong>。在该模块中,我会通过讲述索引的基本原理,层层推进到索引的创建和优化,最后触达复杂 SQL 索引的设计与调优,比如多表 JOIN、子查询、分区表的问题。希望学完这部分内容之后你能解决线上所有的 SQL 问题,不论是 OLTP 业务,还是复杂的 OLAP 业务。</p>
<p>那么在讲完表结构与索引设计之后,业务上线必不可少的就是高可用的环节,而 MySQL 作为一个开源的数据库,虽然提供了大量的高可用解决方案,但或多或少存在不少问题。所以<strong>模块三高可用的架构设计</strong>中,我会层层递进,手把手教你搭建一个完整的、可靠的、符合各种业务类型的高可用解决方案。</p>
<p>除此之外,海量的业务还会涉及分布式架构的设计,这其实对当前业务与 DBA 同学来说,是非常具有挑战性的技术难点。而在<strong>模块四分布式架构</strong>中,我将会从分布式架构概述、分布式表结构设计、分布式索引设计、分布式事务等角度展开。相信我,学完这部分内容,你会觉得分布式并不是一个很难的架构,对于各种分布式架构中的难题,可以做到信手拈来。</p>
<p><strong>模块五偏向拓展</strong>,是对一些数据库设计中热门话题的分析,当你学完前四部分的内容后,进阶学习这些问题,能从更宏观、更上层的角度去设计出一个更好的架构,解决对应的问题,比如热点更新问题、数据迁移等问题。</p>
<p>总的来说,这门课值得你期待,也是我所认为最具有架构实战的 MySQL课程所以我希望你能认真钻研、学透这门课程早日成为一名真正合格的数据库架构师。</p>
</div>
</div>
<div>
<div style="float: right">
<a href="/专栏/MySQL实战宝典/01 数字类型:避免自增踩坑.md">下一页</a>
</div>
</div>
</div>
</div>
</div>
</div>
<a class="off-canvas-overlay" onclick="hide_canvas()"></a>
</div>
<script defer src="https://static.cloudflareinsights.com/beacon.min.js/v652eace1692a40cfa3763df669d7439c1639079717194" integrity="sha512-Gi7xpJR8tSkrpF7aordPZQlW2DLtzUlZcumS8dMQjwDHEnw9I7ZLyiOj/6tZStRBGtGgN6ceN6cMH8z7etPGlw==" data-cf-beacon='{"rayId":"709972f8ba013d60","version":"2021.12.0","r":1,"token":"1f5d475227ce4f0089a7cff1ab17c0f5","si":100}' crossorigin="anonymous"></script>
</body>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-NPSEEVD756"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag('js', new Date());
gtag('config', 'G-NPSEEVD756');
var path = window.location.pathname
var cookie = getCookie("lastPath");
console.log(path)
if (path.replace("/", "") === "") {
if (cookie.replace("/", "") !== "") {
console.log(cookie)
document.getElementById("tip").innerHTML = "<a href='" + cookie + "'>跳转到上次进度</a>"
}
} else {
setCookie("lastPath", path)
}
function setCookie(cname, cvalue) {
var d = new Date();
d.setTime(d.getTime() + (180 * 24 * 60 * 60 * 1000));
var expires = "expires=" + d.toGMTString();
document.cookie = cname + "=" + cvalue + "; " + expires + ";path = /";
}
function getCookie(cname) {
var name = cname + "=";
var ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i].trim();
if (c.indexOf(name) === 0) return c.substring(name.length, c.length);
}
return "";
}
</script>
</html>