互联网数据库架构设计

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

互联网数据库架构设计

一、58同城数据库架构设计思路

(1)可用性设计

解决思路:复制+冗余

副作用:复制+冗余一定会引发一致性问题

保证“读”高可用的方法:复制从库,冗余数据,如下图

带来的问题:主从不一致

解决方案:见下文

保证“写”高可用的一般方法:双主模式,即复制主库(很多公司用单master,此时无法保证写的可用性),冗余数据,如下图

带来的问题:双主同步key冲突,引不一致

解决方案:

a)方案一:由数据库或者业务层保证key在两个主上不冲突

b)方案二:见下文

58同城保证“写”高可用的方法:“双主”当“主从”用,不做读写分离,在“主”挂掉的情况下,“从”(其实是另外一个主),顶上,如下图

优点:读写都到主,解决了一致性问题;“双主”当“主从”用,解决了可用性问题

带来的问题:读性能如何扩充?解决方案见下文

(2)读性能设计:如何扩展读性能

最常用的方法是,建立索引

建立非常多的索引,副作用是:

a)降低了写性能

b)索引占内存多了,放在内存中的数据就少了,数据命中率就低了,IO次数就多了但是否想到,不同的库可以建立不同的索引呢?如下图

TIPS:不同的库可以建立不同索引

主库只提供写,不建立索引

online从库只提供online读,建立online读索引

offline从库只提供offline读,建立offline读索引

提高读性能常见方案二,增加从库

上文已经提到,这种方法会引发主从不一致问题,从库越多,主从时延越长,不一致问题越严重

这种方案很常见,但58没有采用

提高读性能方案三,增加缓存

传统缓存的用法是:

a)发生写请求时,先淘汰缓存,再写数据库

b)发生读请求时,先读缓存,hit则返回,miss则读数据库并将数据入缓存(此时可能旧数据入缓存),如下图

带来的问题:

a)如上文所述,数据复制会引发一致性问题,由于主从延时的存在,可能引发缓存与数据库数据不一致

b)所有app业务层都要关注缓存,无法屏蔽“主+从+缓存”的复杂性

58同城缓存使用方案:服务+数据+缓存

好处是:

1)引入服务层屏蔽“数据库+缓存”

2)不做读写分离,读写都到主的模式,不会引发不一致

(3)一致性设计

主从不一致解决方案

方案一:引入中间件

中间件将key上的写路由到主,在一定时间范围内(主从同步完成的经验时间),该key上的读也路由到主

方案二:读写都到主

上文已经提到,58同城采用了这种方法,不做读写分离,不会不一致

数据库与缓存不一致解决方案

两次淘汰法

异常的读写时序,或导致旧数据入缓存,一次淘汰不够,要进行二次淘汰

a)发生写请求时,先淘汰缓存,再写数据库,额外增加一个timer,一定时间(主从同步完成的经验时间)后再次淘汰

b)发生读请求时,先读缓存,hit则返回,miss则读数据库并将数据入缓存(此时可能旧数据入缓存,但会被二次淘汰淘汰掉,最终不会引发不一致)

(4)扩展性设计

(4.1)58同城秒级别数据扩容

需求:原来水平切分为N个库,现在要扩充为2N个库,希望不影响服务,在秒级别完成

最开始,分为2库,0库和1库,均采用“双主当主从用”的模式保证可用性

接下来,将从库提升,并修改服务端配置,秒级完成扩库

由于是2扩4,不会存在数据迁移,原来的0库变为0库+2库,原来的1库变为1库和3库此时损失的是数据的可用性

最后,解除旧的双主同步(0库和2库不会数据冲突),为了保证可用性增加新的双主同步,并删除掉多余的数据

这种方案可以秒级完成N库到2N库的扩容。

存在的问题:只能完成N库扩2N库的扩容(不需要数据迁移),非通用扩容方案(例如3库扩4库就无法完成)

(4.2)非指数扩容,数据库增加字段,数据迁移

[这些方法在(上)篇中都已经介绍过,此处不再冗余,有兴趣的朋友回复“同城”回看(上)篇]

方案一:追日志方案

方案二:双写方案

(4.3)水平切分怎么切

四类场景覆盖99%拆库业务

a)“单key”场景,用户库如何拆分:user(uid, XXOO)

b)“1对多”场景,帖子库如何拆分:tiezi(tid, uid, XXOO)

c)“多对多”场景,好友库如何拆分:friend(uid, friend_uid, XXOO)

d)“多key”场景,订单库如何拆分:order(oid, buyer_id, seller_id, XXOO)

[这些拆库方案在(上)篇中都已经介绍过,此处不再冗余,有兴趣的朋友回复“同城”回看(上)篇]

(5)海量数据下,SQL怎么玩

不会这么玩

a)各种联合查询

b)子查询

c)触发器

d)用户自定义函数

e)“事务”都用的很少

原因:对数据库性能影响极大

拆库后,IN查询怎么玩[回复“同城”回看(上)篇]

拆库后,非Partition key的查询怎么玩[回复“同城”回看(上)篇] 拆库后,夸库分页怎么玩?[回复“同城”回看(上)篇]

问题的提出与抽象:ORDER BY xxx OFFSET xxx LIMIT xxx

单机方案:ORDER BY time OFFSET 10000 LIMIT 100

分库后的难题:如何确认全局偏移量

分库后传统解决方案:查询改写+内存排序

a)ORDER BY time OFFSET 0 LIMIT 10000+100

b)对20200条记录进行排序

c)返回第10000至10100条记录

优化方案一:增加辅助id,以减少查询量

优化方案二:模糊查询

a)业务上:禁止查询XX页之后的数据

b)业务上:允许模糊返回=> 第100页数据的精确性真这么重要么?最后的大招!!!(由于时间问题,只在DTCC2015上分享了哟)

相关文档
最新文档