微博平台研发做为微博的底层数据及业务支撑部门,已经经历了5年的发展历程。伴随着从数据及业务暴发式增加,咱们在海量数据存储方面遭遇了诸多挑战,与此同时也伴随着丰富经验的积累。 mysql
本次新兵训练营,受众在于应届毕业生,目的在于让新同窗系统化而且有针对性的了解平台的核心技术及核心业务,以使新同窗在新兵训练营结束后,可以对平台的底层架构与业务有必定的了解。 web
本文主要面向新同窗介绍平台的核心技术之一——海量数据存储,主要介绍在海量数据存储在大规模分布式系统下的架构变迁与设计。 redis
课程大纲: sql
1. 课程目标 数据库
2. 存储服务概述 缓存
3. MySQL与MySQL分布式架构设计 服务器
4. Redis与Redis分布式架构设计 网络
5. 思考与讨论 数据结构
1、课程目标 架构
1. 了解存储服务概况,以及RDBMS及NoSQL的差别
2. 理解MySQL、Redis、HBase基本实现机制、特性、适用场景
3. 理解几种存储产品的大规模分布式服务方案
4. 学会使用平台的MySQL、Redis client组件
5. 理解对于MySQL、Redis分布式系统设计想要注意的问题
6. 了解平台几种典型案例
7. 理解几种存储产品在平台的定制修改与名词术语
2、存储服务概述
1. 关系型数据库是基于实体关系模型(Entity-Relationship Model)的数据服务,具有如下特色。
适合存储结构化数据
查询语言SQL,insert delete update select
主流关系型数据库可能是持久化存储系统,系统性能与机器性能相关性较大
几类主流的 关系型数据库
MySQL
Oracle
DB2
SQL Server
性能
局限于服务器性能,与其是磁盘性能
局限于数据复杂度
常见的SSD磁盘服务器,单机读取性能可达万级/s
大型互联网服务大多采用MySQL进行做为关系型数据库,微博平台的核心业务(如微博内容用户微博列表)也一样如此
本次培训也会着重介绍MySQL及其分布式架构方案。
2. NoSQL(Not only SQL)数据库,泛指非关系型的数据库,兴起的契机在于传统关系型数据库应对大规模、高并发的能力有限,而NoSQL的广泛性能优点可以弥补关系型数据库在这方面的不足
存储非结构化数据、半结构化数据
性能
业界使用的NoSQL多为内存集中型服务,受限于I/O及网络,一般请求响应时间在毫秒级别,单机QPS在10万级别(与数据大小及存储复杂度相关)
常见的几类NoSQL产品
K-V(Memcached、Redis),这类NoSQL产品在互联网业内应用范围最广。Memcached提供具有LRU淘汰策略的K-V内存存储;而Redis提供支持复杂结构(List、Hash等)的内存及持久化存储
Column(HBase、Cassandra),HBase是基于列式存储的分布式数据库集群系统
Document(MongoDb)
Graph(Neo4J),最庞大、最复杂的Graph模型是人的关系,理论上用图描述而且用Graph数据库存储最合适不过,不过目前的数据规模、系统性能仍然有待优化
web2.0时代,NoSQL产品在互联网行业中的重要性随着互联网及移动互联网的发展而与日剧增 大型互联网应用,为应对大规模、高并发访问,大多都引入了NoSQL产品,其中Memcached、Redis以其高成熟度、高性能、高稳定性而被普遍使用。微博平台也具有千台规模的NoSQL集群,微博核心的Feed业务、关系业务也都依赖Memcached及Redis提供高性能服务
本次培训,会着重介绍Redis及其分布式架构
3、MySQL
微博平台核心业务的数据都存储在MySQL上,目前具有千台规模的集群,单个核心业务数据突破千亿级,单个核心业务QPS峰值可达10万级每秒,写入也是万级每秒。
在海量数据而且数据量持续增加的景下,在如何设计知足 高并发(w/r)、低延时(10ms级别)、高可用性(99.99%)的分布式MySQL系统方面,咱们已经具有充足的经验而且依然在持续攻坚这一问题,而咱们的课程也会着重介绍海量数据存储之MySQL。
1. MySQL简介
MySQL是一个关系型数据库系统RDBMS
使用SQL做为查询语言
开源
存储引擎
Innodb 支持事务、行锁,写入性能稍差
MyIsam 不支持事务,读写性能略好
知足ACID特性
主键、惟一键、外键(大规模系统通常不用)
Transaction,事务即一系列操做,要么彻底地执行,要么彻底地不执行
服务、端口、实例,都是指 服务端启动的一个MySQL数据库
性能
随着磁盘性能升高,读写性能也逐步升高,但成本也随之增长
数据库的写入性能:写入tps随着并发量增长而增长,但上升到必定瓶颈,增速放缓至并发数临界点后 tps会急剧下滑
思考:若是对性能有更高(超出上述三种存储介质并发量级)的要求怎么办?
定制存储:针对服务特色,定制存储,定制更适合本身业务场景的存储产品。然而通常业界成熟产品为考虑通用性而会牺牲部分性能
引入NoSQL
2. 从单机到集群的架构变迁
业务上线初期,web服务规模较小,通常具有如下特色
服务原型时期,用户基数小,多种业务公用资源,日均写入百万级别,读取千万级别
数据规模小,单机性能可以知足需求
用户规模小,开发重心偏向迭代速度
考虑到上述小型业务特色,为节约资源成本及开发成本,能够采用多个业务混合部署形式
当用户增多,数据量、访问量升高(2倍如下),数据库压力较大,怎样在有限程度提升MySQL吞吐量呢?
SQL优化
硬件升级
压力还在有限的范围内增加,经过简单、低成本优化,能够必定成都上提升有限的服务性能
业务持续发展,读取性能出现瓶颈&&各业务互相影响,多个业务出 现资源抢占,如何快速解决业务抢占问题以提升服务性能?
垂直拆分——按业务进行数据拆分
按业务进行拆分,以使业务隔离,timeline的压力增长,不会影响content数据库服务性能;进行拆分后,资源增长,服务性能也相应提高。
随着业务的继续发展,读取性能出现瓶颈,读写互相影响,如何确保读请求量的增长,不要影响写入性能?相反写入请求量增长如何确保不影响读取性能?(写入性能出现问题会形成数据丢失)
读写分离,写入仅写master,master与slave自动同步;读取仅以slave做为来源
读写分离后,slave仅专一于承担读请求,读取性能获得优化;同里独立的master服务的写入性能也获得优化。
一台/一对M-S服务器性能终归是颇有限的,当单实例服务性能没法承载线上的请求量时,如何进行优化?
升级为一主多从架构
一个master承载全部写入请求,理论上master性能不变
多个slave分担读取请求,读取性能提高n倍
随着业务量的增加,服务出现以下变化:
数据量增加,意味着本来的存储空间不足
写入量增加,意味着master写入性能存在瓶颈
读取量增加,意味着slave读取性能也存在瓶颈,但经过扩充slave是有限制的:一方面M-S replication性能有风险;另外一方面扩充slave的成本较高
如何优化以解决上述问题?
水平拆分
业务经历数据量的增加、读写请求量的增加,数据库服务已经演进为分布式架构,一个业务的数据,怎样合理的分布到上述复杂的分布式数据库是下一个须要解决的问题
3. 如何基于上述演进到最后的架构进行数据库设计呢?
分布式数据库设计
hash拆分方式,既按hash规则,将数据读写请求分散到多个实例上,见上述水平拆分示意图
时间拆分方式,基于肯定好的时间划分规则,将数据按时间段分散存储再多个实例中
数据分布到一个分布式数据库内,一个实例存储1/n的数据,一个实例只须要一个数据库就可以知足功能需求。
经历几年的发展,数据规模会成倍增加,当须要再次水平扩容(4太→8台),须要经过程序,将数据一分为二,数据迁移成本较高,须要开发人员介入。
若是在数据库设计时,一个就预先建好2个数据库 ,每一个数据库存储1/n/2的数据,须要水平扩容时,便可完整迁移一个数据库,而无需开发人员干预。
在一个数据库实例上,创建的多个数据库,称为逻辑库。
逻辑库设计
逻辑库是相对与物理库而言的概念:物理库只数据库服务的实例;逻辑库指在一个数据库实例上建立的多个database
定义逻辑库的目的是便于扩容。假如4台数据库服务器,每台上的物理库包含8个逻辑库,当系统出现容量、写入量瓶颈时,能够新增一倍即4台服务器,直接以同步方式同步数据库,而不须要单独编写应用程序利用进行导入
4. 基于上述分布式数据库下的表拆分设计方式
hash拆分方式:按hash规则将一个数据库的数据,分散hash到多张表中
适合数据规模有限的数据集
适合增加速度可控的数据集
结合数据库的hash模型如图:
根据uid hash到uid所在到数据库,而后再hash到数据库_1下的tb_5表
按时间拆分方式,按时间规则将同一时段的数据存储在一张表,多个时段时间存储在多张表。例如按月划分,每月表存储一个月的数据,若是须要获取所有数据须要跨越多个月表
适合存储增速较快的数据集
但查询数据须要跨越多个时间段的表
结合数据库的hash模型如图:
根据uid hash到所在的数据库db_1,而后再查找201507 201506获取两个月的数据
思考一个问题:如何可以快速定位,一我的的第1000条到1100条数据呢?
二级索引快速定位(一级)索引位置
描述数据在以及索引中的分布情况
用于快速定位/缩小查询范围
通常状况字段列表:uid, date_time, min_id, count
5. 当一台服务器宕机怎么办?
Slave(一主多从)宕机?
剩余健康Slave无风险,则无需紧急操做,例行修复
切换流量到容灾机房(若是具有容灾机房)
紧急扩容[优先]、重启、替换
有损降级部分请求
Master宕机?
因为master数据的惟一性,导致master出现异常会直接形成数据写入失败
快速下线master
下线一台salve的读服务(若是slave性能有风险,则同时快速扩容)
提高slave为master
生效新master与slave的同步机制
6. 如此复杂的分布式数据库+数据库拆分+数据表拆分,client端如何便捷操做呢?
多数使用分布式数据库服务的团队,都有各自实现的数据库Client组件,微博平台采用以下几个层级的组建来进行分布式数据库操做
获取TableContainer,获取全部表定义规则
经过table name从TableContainer中获取指定的TableItem
TableItem关联多个JdbcTeplate-DataSource
经过TableItem结合uid、id、date获取通过hash计算获得正确的JdbcTemplate及SQL
使用JdbcTemplate进行SQL操做
7. 注意事项
MySQL设计应该注意的问题
表字符集选择UTF8
存储引擎使用InnoDB
使用Varchar/Varbinary存储变长字符串
不在数据库中存储图片、文件等
每张表数据量控制在20000W如下
提早对业务作好垂直拆分
MySQL查询应该遇到的问题
避免使用存储过程、触发器、函数等
让数据库作最擅长的事
下降业务耦合度避开服务端BUG
避免使用大表的JOIN
MySQL最擅长的是单表的主键/索引查询
JOIN消耗较多内存,产生临时表
避免在数据库中进行数学运算
MySQL不擅长数学运算
没法使用索引
减小与数据库的交互次数
select条件查询要利用索引
同一字段的条件断定要用in而不要用or
8. MySQL练习题
设计一个每秒2000qps,1亿条数据的用户基本信息存储数据库。完成数据库设计,数据库搭建,web写入查询服务搭建。
定义用户信息结构:uid,name,age,gender
给定2个mysql实例,每一个实例建立2个数据库
每一个数据库建立2长表
编写代码,以hash形式,实现对数据库、表的数据操做
4、Redis
微博做为web2.0时代具有表明性的SNS服务,具有庞大的用户群体和亿级的活跃用户,同时也承担着高并发、低延迟的服务性能压力。
Redis做为NoSQL系列的一个典型应用,以其高成熟度、高可用性、高性能而被用来解决web2.0时代关系型数据库性能瓶颈问题。例如微博的计数服务的请求量以达到百万级/s,数以百计的关系型数据库才能应对如此高的QPS,并且请求耗时较高且波动较大;然而使用Redis这种NoSQL产品,仅仅须要10台级别的集群便可应对,平均请求耗时5ms如下。
这一章节,为你们介绍Redis以及其大规模集群架构。
1. Redis简介
Redis是一个支持内存存储及持久化存储的K-V存储系统
支持复杂数据结构,相比与Memcached仅支持简单的key-value存储,Redis原生支持几类经常使用的存储结构,例如
hash:存储哈希结构数据
list:存储列表数据
单线程
高性能,避免过多考虑并发、锁、上下文切换
数据一致性好,例如对一个计数的并发操做,不会有‘读者写者’问题
单线程没法利用多核,单能够经过启动多个实例方式,充分利用多核
原生支持Master-Slave
过时机制
被动过时——client访问key时,判断过时时间选择是否过时
主动过时——默认使用valatile-lru
volatile-lru:从已设置过时时间的数据集中挑选最近最少使用的数据淘汰
volatile-ttl:从已设置过时时间的数据集中挑选将要过时的数据淘汰
volatile-random:从已设置过时时间的数据集中任意选择数据淘汰
allkeys-lru:从所有数据集中挑选最近最少使用的数据淘汰
allkeys-random:从所有数据集中任意选择数据淘汰no-enviction(驱逐):禁止驱逐数据
Redis的字典表结构
Key字典表hash table结构,有hash结构就意味着须要按需进行rehash,rehash的时间段内,对内存是有成倍开销的
Value结构,存储Key对应的value
Expire表结构,存储key的过时时间
额外开销60B+
持久化方式
AOF
Snapshot——RDB文件快照
与MC的差别
平台的定制CounterService
修改hash table为,增量扩展式的hash tables,例如每1亿个key存储在一个table中,数据超过1亿(或者一个临界比例)则开辟下一个1亿空间的table
废弃expire,Redis的主动过时策略没法像MC的LRU策略确保热数据留存在内存中,冷数据从缓存剔除,咱们多数场景须要控制Redis中的数据量不突破内存限制
2. Redis的主要数据结构
String (key-value)
Hash (key-field-value)
List(key-values)
Set(key-members)
SortedSet(key-member-score)
3. Redis的分布式部署方案是怎样的?与MySQL有什么异同
Reids因为其M-S特性与MySQL相似,所以分布式部署方案同MySQL至关
单实例——小型业务 or 业务初期
主从——HA、读写分离
一主多从——读取性能出现瓶颈
数据水平拆分——容量不足|写入性能瓶颈
经常使用的分布式部署方案
4. 分布式Redis架构如何实现高可用(HA)?
采用M-S高可用方案,缘由也式因为其Master-Slave的特性
服务域名化是必要的,目前大型的Redis集群应用大多采用域名方式
5. 基本容量规划
空间=key数量*单条占用(K-V占用+额外空间) 用户空间=5亿用户*200B(平均)=100G 微博计数器=(500亿+预期2年新增300亿)*10B=800G
访问量=服务访问量*单次访问对资源的hit量 微博计数器Feed访问量=10000/s * 20 = 20万/s
6. CounterService
微博具有庞大的数据基数,所以所须要存储的数据量级也极其庞大
例如微博计数器,具备百亿条纪录,所有存储在Redis中,须要T级别的空间,成本太高
所以咱们对Redis进行定制化改造,以使其适合多数数据小,大小有固定限制的数据
优化存储空间
采用分段哈希桶的形式,进行存储,避免rehash (分段存储要求key为递增序)
空间占用优化效果
key:8B
value:自定义
7. 如何支持上述分布式架构下的client访问?(redis3.0+支持Redis Cluster)
Reids具备多个开源的client支持,咱们所使用的是Jedis
Jedis除了提供client外,还提供了操做封装以及M-S组件
咱们所使用的Redis系列组件以下:
8. Redis练习题
使用Redis,实现用户受到的赞列表及赞计数功能
使用测试环境,启动两个Redis实例
使用Redis存储用户受到的赞列表[{uid, time}..]及赞计数uid-count
完成赞操做业务逻辑,包括赞、取消赞、查看赞列表、查看赞计数
5、思考与讨论
1. Memcache当容量到达瓶颈会 截取LRU链以释放空间。上文介绍过Redis的key过时机制,思考如下几个问题:
Redis满了会发生什么?如何避免发生上述问题呢?
为何咱们的定制Redis会废弃expire表?
2. MySQL与Redis各自适合什么样的场景?
数据冷热?
数据大小?
数据量级?
数据增加速度?
是否持久化?
访问量(read/write)?
请求性能要求?
------------------新兵训练营简介------------------
微博平台新兵训练营活动是微博平台内部组织的针对新入职同窗的团队融入培训课程,目标是团队融入,包括人的融入,氛围融入,技术融入。当前已经进行4期活动,不少学员迅速成长为平台技术骨干。
微博平台是很是注重团队成员融入与成长的团队,在这里有人帮你融入,有人和你一块儿成长,也欢迎小伙伴们加入微博平台,欢迎私信咨询。
------------------讲师简介------------------
毕建坤,@bijiankun 微博平台及大数据部——平台研发系统研发工程师,2012年7月毕业于哈尔滨理工大学,校招入职微博工做至今,前后负责微博Feed、赞、评论等底层服务研发以及方案评审等工做。聚焦大规模系统的架构设计与优化,以及大规模系统下的服务稳定性保障。新兵训练营第一期学员。