背景知识
大型网站为了软解大量的并发访问,在网站实现分布式负载均衡,但远远不够。到了数据业务层、数据访问层,如果还是传统的数据结构,或者只是单单靠一台服务器来处理如此多的数据库连接操作,数据库必然会崩溃,特别是数据丢失的话,后果更是不堪设想。这时候,我们会考虑如何减少数据库的连接,这就是下面要提到的读写分离,下面本篇设计读写分离优点。
1. 减缓主数据库压力
2. 自动扩容从库以满足用户对数据库读请求
3. 提供接口让用户基于对数据强一致性要求来选择是否读从库
常见方案
方案一:
应用端方案,优点:路由策略可扩展可控制,缺点:与应用程序耦合,关键技术:Sprint AOP,典型产品:Spring MVC + mybatis[code control datasource]
方案二
驱动方案,优点:Mysql ReplicationDriver,缺点:与应用程序耦合,关键技术:Keep connection of origin database base on ReadOnly True/False, 典型产品:com.mysql.jdbc.ReplicationDriver java
方案三
中间件方案,优点:与应用程序解耦,缺点:增加维护中间件effort,丢失一下性能,关键技术:数据库代理,典型产品:Mysql Proxy (kingshard)、Amoeba、Atlas
详细设计
下面是中间件读写分离设计大致思路:
1. 写及事务操作在主库
2. 读操作基于用户数据强一致性需求决定是读从库还是主库通过调用接口
3. 从库监控基于cpu/conn etc来自动伸缩
4. 从库负载均衡
基于上述思路,下面是相应的解决方法
1. 划分读,写及事务接口
2. 读是否走从库控制接口
3. 建立中间层及db自动伸缩的联系枢纽
4. 从库监控及伸缩
5. 设计负载均衡策略
划分读,写及事务接口
读接口
SelectOne
SelectAll
Exists
Count
写接口
InsertOne
InsertAll
UpdateOne
UpdateAll
Upsert
Delete
事务接口
WraperTransaction
读是否走从库控制接口
EnableReadLoadBlance
建立中间层及db自动伸缩的联系枢纽
基于etcd 的特点:simple, secure, fast and reliable,选择etcd作为中间层及db的信息桥梁
设计kep/value pair
key: region/dbname/host:port
value: username:passwd@tcp(hostname:port)
中间层实时获取db list
利用Get and Watch github.com/coreos/etcd/clientv3 实时更新从库列表
db 注册及销毁
1. 部署新从库,注册key/value into etcd
2. 下线从库,先delete key from etcd, 然后基于中间层超时时间或者从库连接数来平滑下线,以免break正在running request
3. 监控db状态,发现down及时delete key
从库伸缩策略
监控metrics
从库伸缩主要是基于下面这些metrics:
1. CPU load. >5
2. Memory Usage >80%
3. iostat await > 5ms %util >80%
4. open connThreads_connected > 80% max_connections
5. using conn Threads_running >90% mysql highest throughput conn number
任一条命中均代表mysql overload
扩展新的节点
超过一半节点overload,就增加新的节点,可以start 一个standby的节点作为候选,这样可以快速投入应用
缩一个节点
90%的节点在两天内应用conn < 5,下线一个节点
设计负载均衡策略
Round Robin plus filter
Round robin (pick the next in list) and using conn < 30 (Optimal number of parallel connections)
All slave nodes using conn >= 30, random algorithm select a slave node list
No slave nodes on all zone, fall back to master node
网友评论