前两天 Uber post 了一篇文章(参考文末阅读),说他们从 Postgres SQL 转到使用 MySQL 了。blog 写的不错,科普了一些 DB indexing 和 replication 的基本常识。当时转给一个朋友看,朋友说,其实 Uber 2013年才发了一篇文章说他们从 MySQL 转 Postgres SQL。遂去找来看了。看完后寻思下,其实两篇文章背后的情况,两次转型的文章背后的原因,也就可以揣测一二了。
作为两大主流开源数据库,MySQL 和 Postgres 的 “战争” 从来没有停止过,虽然硝烟不似程序语言之间的斗争那么浓烈。你可以去 Quora 或者 Stack Overflow 上搜相关的 MySQL v.s. Postgres 帖子,特别多。我的感觉是,各有各的优势和实用场景,并没有一种比另一种有压倒性优势的存在。
对于大部分程序员来说,公司用哪个 DB,基本不太轮到你来做决定。你加入一个公司的时候,除非是创业公司,或者你是 CTO、VP、Director 级别的,否则大部分的技术选型都应该早已经尘埃落定了的。尤其是 DB,一旦选择,再迁移的代价就很大。所以除非有了颠覆性的优势或者问题,很少有公司会去费时费力做这种大的迁移。而不论是选型还是转型,一个不可忽略的因素,就是你招到的工程师更能驾驭哪一种技术,或者有话语权的决策者们倾向于哪一种技术。这其实和程序语言的选型多少有着异曲同工的类似。
其实 Uber 两次高调转型,类似的事情在 Square 也发生过。虽然 Square 最早是使用 MySQL,但是在大概在 2012 年间,因为 Postgres 的各种优势(如对 geospatial 数据及搜索的支持等),以及当时几位比较 senior 的工程师的大力倡导,很多新的 service 都尝试性地选择了使用 Postgres。所以当时公司的架构是 MySQL 和 Postgres 并存。对于那时候的我而言,不过是有机会学习、了解、和比较两个不同的技术。两者各有特点,有些东西在 MySQL 里似乎更方便,另一些则反之。总有方案去实现,并没有觉得非要哪一种才行。
DB 若安好,便是晴天。
一个公司,如果 DB 从来不出问题,那肯定是因为没有业务或者流量。所有的技术,都有它设计的应用场景。除了一些 happy case,就一定有坑。能够尽可能地避免这些坑,或者在出问题的时候能够最快修复,就成了至关重要的因素。Square 两种 DB 并存的期间,公司里 Postgres 的牛人寥寥无几。但是 MySQL 的 experts,却有几个极为靠谱的。大部分工程师,并不是数据库专家,Postgres 和 MySQL 的相对优势,对我们而言,都比不过出问题的时候有人解惑或者救火来的重要。何况一个公司维系两套同类的数据库系统本身就是个负担。因此,这些使用 Postgres 的 service 后来又都慢慢转成 MySQL 了。
因为我们做支付的需要强 transactional 的支持,所以不太会用 NoSQL 类型的,主要用的还是 MySQL 或者 Postgres。虽说数据库相关的知识和技术,现在工作中因为用得多,慢慢也了解了不少,但如果真的线上出了问题,自己还是不太摆得平。好在每个公司都会有一些数据库大牛,有的公司叫做 DBA。很多中小公司并没有专职的 DBA,都是做系统的人监管。有几位私交甚好。加上自己平时系统里相关问题也经常需要请教,所以一来二去知道了好些好玩的事情。
对数据库大牛我一向是抱景仰的态度的。公司只要稍具规模,数据库这块做不好,基本也就没啥好玩的了。这一块不出问题也罢,一出问题,基本就是见血封喉,网站直接挂掉。那么平时最常见的都有哪些问题呢?
首先就是选型。
每个公司因为业务的不同,数据库系统应用场景不一样,哪一种最合适就不一样。没有哪一个系统一定是最好的。比如做支付的一定要强事务性、一致性的支持,而很多社交平台更多时候其实是需要高可用;有的业务 writes 特别 heavy,有的业务更重要的是 reads;有些业务可以只关心最近几天的数据,因此可以 tradeoff 老数据读写的低效,有的却要频频 access 历史数据;有些业务可以通过加 index 解决 query 效率,有些却只能通过加缓存等等。。这也是为什么很多公司有多个数据库系统并存,以最优化对每个场景和业务的支持。
选型错了,基本就掉在坑里了,也没有频频踩坑一说了。
另外一个就是相关架构。
什么意思呢?这里包括数据库上层的 cache 系统的设计,程序语言对 DB connection 的处理,proxy layer(如果存在)的功能,以及和 binlog 等相关的 data pipeline 的搭建。当然,也包括数据库系统的分区、备份等的具体设计。很多公司早期所有的 table 都在一个 DB 里面,因为各种 connection pool 和 throughput 的限制,这其实基本没法 scale。能够合理的安排不同 table 的分离,让数据相关的留在一起,不相关的或者不太相关的放在另一个 DB 里。类似这些很简单的道理,很多时候却可以很大程度上缓解 scalability 的问题。
而平时我们遇到的最多的问题,还是 human mistake.
再好的系统,使用姿势不对,也是枉然。何况并不是所有的工程师都是数据库专家。
人为错误分成两种。
一种是 DB operation 中犯的错误。这种概率比较低,但是通常危害却最大。几乎所有的公司都会有类似的传奇,常见的版本有:
- 某某工程师或无意或有意,“不小心” 删掉了数据库某 core table 中所有的数据。不是开玩笑,这种事 Facebook 也发生过,还是一个朋友。好在后来恢复了。这事也成了他的工程师历史上光辉的一笔。
- 某某工程师做 online schema change 的时候,不小心有一步误操作。结果数据库被 lock 长达几个小时。该公司网站也就挂了好几个小时。
- 最后这个版本听国内一个大公司的朋友说的,细节还真是不记得了。只是记得两台服务器,做 master slave switch 还是什么的时候,拔错了一个电源插头,然后。。。就没有然后了。
另一种是程序员程序里或者脚本里犯的错误。这个就很常见了。举个很简单的例子。我们知道 Ruby on Rails 对数据库的 access 基本是通过 Active Record 来完成的。Active Record 可以通过一个 connection pool 来限制每个 application 到 DB 的 connection。如果某一个程序或者脚本中的 query 是查询没有被 index 的数据,而导致 full table scan,加上一些 web server 的并行的实现,很经常就会有整个 DB 的所有 connection 被占用,连 kill query 都没法执行。只能人肉的去做一些类似重启的操作。还有更常见的,就是程序里的 N+1 query。这些都很无语,但若说你从没遇到过,那可能是……呵呵。
最后一种,也就是自然流量增长或者流量突增造成的数据库访问瓶颈。
只要是数据库,就有 throughput 的限制。只要你的业务在增长,总有一天数据库访问就会达到一个上限。所以在这个预警到来前,就要做各种 horizontal 或者 vertical 的 scale 来不断提升这个上限。或者是通过缓存等其他机制来对访问量进行分流。这里面可以做的东西就多了。觉得可以单独写一篇了。
另一种就是类似 DDoS、Marketing 等等带来的各种流量的突增。如果是有计划的 Marketing 等,就需要提前做好各种战斗准备。如果是恶意攻击,那就只能靠各种防御工程(如 IP blocking 等等)挡掉这些访问来保证数据库正常工作了。
最后,推荐一个 DBA 写的博客网站内容很精彩,有技术有情怀。文章写的比我好多了。
题图:Mark Bird
参考阅读:
DBA 博客网站(http://dbanotes.net)
为什么Uber转向使用 MySQL(https://eng.uber.com/mysql-migration/)
本文来自微信公众号“嘀嗒嘀嗒”(ID:AngelaTalk),授权数据分析网发布。作者朱赟(Angela),美国硅谷 Airbnb 的资深工程师。
本文采用「CC BY-SA 4.0 CN」协议转载自互联网、仅供学习交流,内容版权归原作者所有,如涉作品、版权和其他问题请给「我们」留言处理。