V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐工具
RoboMongo
推荐书目
50 Tips and Tricks for MongoDB Developers
Related Blogs
Snail in a Turtleneck
leebs
V2EX  ›  MongoDB

mongodb 数据全量加载到 redis,怎样提升速度?

  •  
  •   leebs · 2022-03-07 16:53:07 +08:00 · 3752 次点击
    这是一个创建于 752 天前的主题,其中的信息可能已经有所发展或是发生改变。

    假设 50w 数据,db 全量查询,再往 redis 里面塞,内存可能会爆。 db 分页查询,需要先 count ,是个耗时的操作,而且分批次插入,最终结果和数据库不一定一致(中间可能有其他删除修改的操作)。

    比如布隆过滤器,一般是怎么导入亿级数据的?

    22 条回复    2022-03-09 12:06:51 +08:00
    hidemyself
        1
    hidemyself  
       2022-03-07 16:54:39 +08:00
    cursor ? MySQL 和 PG 是可以的
    wqhui
        2
    wqhui  
       2022-03-07 17:46:38 +08:00
    分批弄数据进去,导数据过程中发生修改的数据记录一下,这部分数据再刷一下
    git00ll
        3
    git00ll  
       2022-03-07 20:26:04 +08:00
    你只能做到 redis 与 db 中的某个瞬间的数据是一致的,不可能保证恰好与导入完成时数据一致。考虑看业务上能否改。
    另外 redis 写时,开 20-30 线程一起写会快很多。
    wellsc
        4
    wellsc  
       2022-03-07 20:27:30 +08:00
    为什么要全量导入啊,增量不行吗?你确定所有数据是热数据?
    wellsc
        5
    wellsc  
       2022-03-07 20:27:56 +08:00
    @git00ll 你是哪个版本的 redis 哦
    hopingtop
        6
    hopingtop  
       2022-03-07 20:39:14 +08:00
    不严谨回答:如果是 mongodb 全量数据,可以考虑采用 mongodb 的内存引擎 你可以了解一下
    git00ll
        7
    git00ll  
       2022-03-07 21:31:48 +08:00
    @wellsc 与哪个版本的 redis 没有关系,因为应用与 redis 网络交互 RTT 的存在,单线程写很难达到 1000 次 /s 。
    wellsc
        8
    wellsc  
       2022-03-07 21:44:23 +08:00
    @git00ll pipeline 用了吗
    q1angch0u
        9
    q1angch0u  
       2022-03-07 22:11:59 +08:00
    不一直问题可以用线上双写解决吧~
    visitant
        10
    visitant  
       2022-03-07 23:23:20 +08:00
    可以试试接 mongoDB 的 binlog ,然后写入 redis ,看你的业务能不能接受最终一致了
    Mithril
        11
    Mithril  
       2022-03-07 23:36:35 +08:00
    确定一个时间点,比如当前时间,然后把所有 update time 在这之前的数据全拉出来塞到 redis 里。可以想办法跳过序列化和反序列化,直接塞进去。
    然后你去查在这时间点以后的 change stream ,按顺序拉到 redis 里。MongoDB 已经给你这功能了,就不要再用 binlog 了。
    从此以后用 change stream 同步修改,就可以保证大部分时候都是一致的。
    bthulu
        12
    bthulu  
       2022-03-08 08:17:59 +08:00
    去掉 mongo, 全部采用 redis 就行了
    leebs
        13
    leebs  
    OP
       2022-03-08 09:23:47 +08:00
    @bthulu 以前的数据怎么导入呢。
    leebs
        14
    leebs  
    OP
       2022-03-08 09:25:43 +08:00
    @wqhui 按一千条分批查询,MongoDB 查询后面十几万数据很慢,每次读都需要三四秒的时间。
    leebs
        15
    leebs  
    OP
       2022-03-08 09:52:12 +08:00
    @hidemyself 用 cursor 感觉很慢啊。
    leebs
        16
    leebs  
    OP
       2022-03-08 09:53:06 +08:00
    @git00ll redis 不是单线程处理事件的嘛,开多少线程也是一个一个处理的吧。
    leebs
        17
    leebs  
    OP
       2022-03-08 09:53:48 +08:00
    @wellsc 比如要校验数据是否存在,得先把数据全量导入 redis 。
    wellsc
        18
    wellsc  
       2022-03-08 12:07:11 +08:00
    @leebs 布隆?
    zmzeng12
        19
    zmzeng12  
       2022-03-08 22:42:59 +08:00
    @leebs
    redis bulk 写入有两个重要的优化,应该先试试:
    1. redis pipeline
    2. 多线程 /进程并发写入 redis ,redis server 端采用 IO 多路复用设计,加上纯内存操作,因此性能很高,因此 client 端要上多线程才能榨出 QPS 上限,规格不是很小的话,写入数万 QPS 都是很正常的,可以参考华为云给的性能白皮书 https://support.huaweicloud.com/pwp-dcs/dcs-pwp-0606002.html

    如果只是做数据存在 /重复校验,不需要导入全量数据到 redis ,可以参考:
    1. 按 @wellsc 的回答用布隆过滤器解决,看 https://redis.com/redis-best-practices/bloom-filter-pattern/
    2. 如果数据 primary key 能比较好地一一映射成数字,也可以通过 bitmap 解决
    leebs
        20
    leebs  
    OP
       2022-03-08 23:33:09 +08:00
    @zmzeng12
    1. 用布隆过滤器,首先得把数据导进去把。
    2. 数据无规律,都是用户提交的任意数据,有什么好的映射方法嘛。
    leebs
        21
    leebs  
    OP
       2022-03-08 23:33:58 +08:00
    @zmzeng12 另外主要性能影响不在 redis 写入这一边,在 db 数据读取这一边。
    fov6363
        22
    fov6363  
       2022-03-09 12:06:51 +08:00
    update_time 建索引,用 update_time 来导数据,只导 update_time > last_sync_time 的数据
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1222 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 38ms · UTC 23:21 · PVG 07:21 · LAX 16:21 · JFK 19:21
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.