多机房 : 主备机房
多机房是为了解决机房单点问题。
主备机房 : 在主机房所在的城市再建设一个备机房 , 整个备机房的内部完全复制主机房架构 , 在正常情况下仅主机房工作。
主机房与备机房通过专线做存储层数据复制。 (专线是一种特殊的网线,专线通信安全性好、通信质量高)。
主机房出现故障时,备机房经过如下操作代替主机房
- 将备机房存储层的所有从库都提升为主库 。
- 修改 DNS 解析地址指向备机房 , 逐渐接入用户请求 。
同一城市部署的主备机房架构也被称为 “ 同城灾备 “。
优点是搭建简单
缺点:
- 备机房大部分时间处于空闲状态 , 造成大量资源浪费。
- 可用性存疑,理论上备用机房是可以代替主机房工作的,但是备用机房没有实际处理过请求,不一定可用。( 根据笔者的实际经验 , 需要备机房挂帅的时候它总是掉链子)。
多机房 : 同城双活
存储层改造
将两个机房的接入层 IP 地址都配置到 DNS。
两个机房都能负责一部分用户请求 , 形成了 “ 双活 ” 的局面 。
- A 机房与 B 机房组成 “ 双活 ” 机房 , 并由 DNS 负责决定将用户请求分流到哪个机房。
- 两个机房的服务可以通过专线实现互相访问 , 即 “ 跨机房调用 ”。
上述“双活”机房还存在一个问题: 备机房 ( 即 B 机房 ) 存储层的数据库是 A 机房的从库 , 从库意味着只能读数据 , 不可写数据 , 也就是 B 机房无法处理写请求。
B 机房的所有写数据请求在访问存储层的数据库时 , 直接跨机房访问 A 机房对应的主库无论是将数据写入 Redis 、 MySQL 、 MongoDB 还是写入其他存储系统。
那么是否存在跨机房调用而增加延迟呢?
不存在
- 大多数情况下是 读请求大于写请求的。 也就是写请求的用户流量占比极低
- 两者的物理距离很近,在专线通道的加持下跨机房请求的代价极低 , 延迟只会增加 5ms 左右。
所以可以将“同城双活”机房看成是一个机房。
灵活实施
- 物理距离适当,不可以太近,太近可能所有机房都遭受灾害;不可以太远,太远延迟高。
- 可以部署“同城多活”,有多个机房,保证在存储层选出唯一的主机房就好。
分流与故障切流
分流实现方式
- 实现方式是可以根据用户 ID ( UserID )或客户端设备 ID ( DevicelD ) 将用户请求哈希映射到不同的机房 。
- 建议使用 DevicelD来做哈希映射 , 这样可以使得未登录账号的设备也能被分流。
客户端分流
服务端与客户端配合来实现准实时分流。
创建一个分流配置平台并将其部署在各机房 , 工程师可以在这个平台上配置各个域名的分流比例 。
一个域名的分流配置项可以被设计为如下结构 :
"api.friendy.com": {
"sharding" : 100,
"idc": [
"changping":{
"lower": 0,
"upper": 50,
"domain": "api-cp.friendy.com"
},
"yanping":{
"lower": 50,
"upper": 100,
"domain": "api-yq.friendy.com"
}
]
}
- sharding : 表示 DevicelD 经过哈希运算后的取模值 。 对sharding取模。
- ide : 多活机房配置 , 每个机房都有唯一专用名称 , 比如 changping 表示昌平机房 , yanqing 表示延庆机房 。 为每个机房都配置了如下字段:
- lower 、upper : 如果 DevicelD 哈希取模值在 [ lower, upper) 区间 , 需要将请求发送到对应的机房 。
- domain : 机房的专用域名 , 这个域名只会被解析到对应的机房 。