选择你喜欢的标签
我们会为你匹配适合你的网址导航

    确认 跳过

    跳过将删除所有初始化信息

    mongodb单表亿级数据的拆分方案

    技术 2021-09-18 19:21

    声明:该文章来自(三月沙)版权由原作者所有,K2OS渲染引擎提供网页加速服务。

    拆表是一种常见的解决单表数据库瓶颈的方案,在实际的应用场景中能够部分解决单表的写压力和读压力,但是也会带来一些更复杂的影响:

    • 聚合查询变得困难
    • 拆分的键一旦选定,更改会非常困难
    • 拆表的过程要保证线上业务不受影响,操作复杂度高

    因此,表的拆分一定要选在恰当的时候进行,过早,付出很大代价也并不会带来性能的提升,过晚,数据量庞大,操作难度加大。

    在本次实施的拆分方案中,数据特点是:

    • 单表过亿
    • 业务数据是用户对资源的收藏,结构比较单一
    • 只做单向(用户—>数据)查找,不要求反向(数据—>用户)查找
    • 数据处于实时变更状态(新增、删除、查询等操作并存)

    如何选择拆分键

    本例中,拆分的键就是用户 id,且每个用户关联的资源数据最大不会过万。

    如何保证拆分的过程中不影响用户的操作?

    本例中,表中的数据基本上只有如下操作

    • 用户新增一条数据
    • 用户删除一条数据
    • 用户查询数据(有翻页)

    拆表的基本原理就是对选择的键进行 hash 生成每个键所属的表空间名,也就是说,在任意时刻,任意用户的数据只有以下三种状态

    1.全部在旧表中

    2.部分在新表,部分在旧表

    3.全部在新表中

    数据拆分的具体工作是要离线进行的,为了能保证用户数据在这样三种状态之下依然具有像单表中一样的一致性,需要业务层在处理当前用户数据时判断用户是否在迁移中,只有处于迁移状态之下,用户数据才需要特别处理。

    迁移状态如何判断?

    当用户数据处于迁移状态,为了保证用户数据全部可用,即要做到不跨表翻页,我们做了如下决定:一旦开始迁移,用户的全部数据就会载入到一个特殊区域(这里我们用了 redis,后面再讨论这样处理可能带来的问题)且保存为有序集数据。

    如果用户处于迁移状态,则用户的数据一定存在于这个区域,暂且给此区域命名为 on_progress

    迁移状态下如何保证用户数据的正确性?

    当用户处于迁移状态,用户新增一条数据,则在新表、on_progress 、旧表中各写入新增数据,用户删除一条数据,则在新表、on_progress、旧表中同时删除该数据。

    这样做的目的是什么?

    处于迁移状态下的用户,on_progress 中保存了其所有数据,可以进行翻页操作,on_progress 中的所有数据会在离线状态下不断写入新表中,迁移完成之后,旧表中的数据将被删除,on_progress 中数据也将被清除,这样用户数据全部进入新表中,后续的所有操作将只在新表上进行。

    on_progress 中的数据在不断写入新表的过程中,是按照由新—>旧或由旧—>新的顺序进行,在这个过程中:

    用户删除一条数据


    1)有可能该条数据已经写入新表中,所以删除操作要在新表中执行。

    2)on_progress 中的数据要始终和用户所有的操作同步来保证数据的正确性和一致性,因而删除操作也要在 on_progress 中执行。

    3)如果发生意外导致 on_progress 不可用,为维护数据的一致性,删除操作也需要在旧表中进行。

    用户新增一条数据


    1)on_progress 中的数据要始终和用户所有的操作同步来保证数据的正确性和一致性,因而 on_progress 需要写入一条数据。

    2)在某些边界条件下,on_progress (假如数据由旧—>新写入新表) 中的数据迁移完成但还未被删除,用户恰巧写入一条数据,此时用户仍处于迁移状态中,但是离线的迁移操作已经认为迁移停止了,因而此时新增数据需要进入新表才能保证数据最终是正确的。

    3)如果发生意外导致 on_progress 不可用,为维护数据的一致性,新增操作也需要在旧表中进行。

    on_progress 的选择

    在这个方案的实施中,on_progress 用了 redis 的有序集,键就是用户的 id,只要检测到用户 id 的存在就认为该用户处于迁移状态中。

    迁移完成之后,先删除旧表中的数据,然后再删除 on_progress 中有序集。

    判断用户迁移状态

    1.只要用户处于 redis 中,则此时一定是迁移中或迁移完成

    2.只在旧表中找到用户数据,则该用户一定还没有开始迁移

    3.只在新表中找到用户数据,用户已经迁移成功

    需要注意的是,选用 redis 可能带来的问题是 redis 宕机会导致迁移中的数据无法恢复(redis 未开持久化操作或其他原因导致数据不能恢复),只要用户在旧表中有数据存在,则用户删除数据的操作一定也要在旧表中执行,再次恢复迁移时,清除旧表数据,直接载入旧表中的数据到 on_progress


    关注我们

    [超站]友情链接:

    四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
    关注数据与安全,洞悉企业级服务市场:https://www.ijiandao.com/

    图库