1.水平拆分方法
(1)范围法(自增长唯一标识进行数据拆分)
(2)hash法(通过对数据的唯一标识进行计算取模,路由到对应的库表)
2.水平拆分后碰到问题
1.对于只通过唯一标识进行查询业务,很好解决,直接哈希 唯一标识即可,但是通过非 “主属性” 进行 查询就有问题了。无法进行路由选择。
2.那么问题产生的具体业务是什么?举例说明:用户登录:可能输入账户号、邮箱号、手机号进行登录。但是这些都不属于 主属性。那么业务服务发起查询请求的时候,怎么给其路由到对应的分库中呢?这就是需要设计解决方案了。管理类业务:基本上不关注具体某个用户的数据,通常来说,都是站在某个维度进行访问数据。例如,管理员需要查询状态为屏蔽的用户有哪些?管理员需要查询最近七天活跃的用户有哪些?这些角度都是站在纵向的角度进行操作。那么就导致了一个问题,产生了分库分表操作后,业务将不能进行。
3.解决方案
建立起 非主属性 与主属性之间的关系。产生关系映射。那么建立一张表,这张表中 存储了 用户ID与 用户状态、用户最近活跃时间。那么我们就可以通过查询 “禁用”的状态的 用户ID有哪些?就可以查询出“近期活跃”的用户ID有哪些?然后进行正常的业务操作了。
那么说到这个地方,那可能有童鞋会疑问,通常来说,正常人的思维不都是 以 ID 查询 NAME吗?这里为什么用NAME查询 ID?合适吗?方便吗?那么这个使用就可以使用 “倒排索引”的概念了。 依照之前写的一篇文章:什么是 ES?什么是倒排索引。那篇文章解释了,看一下你就会回来说,诶,是这么个道理诶。
4.线上环境如何 优雅的扩容(PS:不停服,更新???)
王者荣耀,刺激战场,很火爆。相信很多人都会在不同的时间段进行玩这个游戏。那服务器怎么扩容呢?随着用户量的激增,那么数据库的读写性能也会随着降低,怎么解决呢?需要扩容的话,怎么做到用户无感知扩容呢?相信很多老玩家肯定碰到过“王者荣耀更新公告:不停机升级。” ”王者荣耀更新公告:停服 0:00 ~ 23:59,升级“。那么停服升级,我们可以很好理解,停服升级嘛:构建N个新的库,结构一致,那么将路由扫描进行添加这N个库,就可以取模运算到N库中。然后将对应的原Old库中的数据,重新取模运算,如果是其他库的,将进行数据迁移。将老数据进行新的均衡分配。那么再重新启动服务,那就完成了数据库的升级扩容,并且解决了老数据迁移问题。
但是有个问题:停服扩容固然好用。但是不够优雅,对于用户角度来说,只是一个升级扩容,不是什么大动作。直接停服了。那用户体验很差。那下面就说一下 优雅扩容的 解决方案:
-
举例说明:原 2个库,现准备增加 2个库。
-
那么原 2个库 中有 5个用户了。 用户1、用户3、用户5 原先路由到db1; 用户2、用户4 原先路由到db2;
-
那现在 第一步;先搭建好 对应的2 个库。建立为对应,分别建立同步关系(触发器) db3 同步 db1 中数据; db4 同步 db2 中的数据;然后现在情况是:用户1、用户3、用户5使用 db1 中的 数据, 那么db3可以理解为从库,保持与db1中的数据一致。 同理:db2 与 db4;
-
然后,修改服务的配置,将2个库改为4个库,重启业务服务,那新的路由策略生效,用户1、用户3路由到db1; 用户2原先路由到db2; 用户5路由到db3; 用户4原先路由到db4; 业务正常进行
-
再断开db3对主库的同步、断开db4对主库的同步。保证其他脏数据不再增涨,然后将四个库中属于其他库的数据全部清空。那么完成数据收缩操作。
-
完成优雅的数据库扩容操作。其他操作也同理。
思路来自互联网中某个大佬,用自己的语言描述了一下