V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
bccber
V2EX  ›  程序员

我这个服务端 有必要使用内存映射文件吗?

  •  
  •   bccber · Apr 20, 2017 · 4138 views
    This topic created in 3302 days ago, the information mentioned may be changed or developed.

    我有服务端 A 每天半夜需要从 mysql 加载大量数据到内存 数据格式大约为 map<int64, set<int32>> 加载完数据大概要 5,6 分钟

    如果程序挂逼 也需要花费 5,6 分钟加载数据 相当于会停止服务 5,6 分钟

    为了解决这个问题,另外搞了一个小服务 B 作用就是每天半夜把 mysql 的数据生成到内存映射文件(5 个 GB 左右)

    服务 A 需要加载数据时就直接加载内存映射文件 速度快 然后服务 A 直接操作内存映射文件

    一直运行 也没出过什么错误 但想想 好像没必要使用内存映射文件:

    1. 映射文件只读不修改
    2. 数据只有 5G 左右,完全可以放到物理内存

    我现在的想法是:服务B生成内存映射文件, 服务A从内存映射文件加载数据物理内存,然后关闭文件

    19 replies    2017-04-24 16:43:12 +08:00
    trys1
        1
    trys1  
       Apr 20, 2017 via Android
    楼主的技术栈有点窄,完全有其它不同的方案可以满足你怪异的需求,不信你问楼下
    ihuotui
        2
    ihuotui  
       Apr 21, 2017 via iPhone
    就 nio mmap 就可以了, rocketmq 都是这样做的,看看 mq 的 store 代码
    ihuotui
        3
    ihuotui  
       Apr 21, 2017 via iPhone
    就是你现在的内存映射文件
    billlee
        4
    billlee  
       Apr 21, 2017
    把这个文件放到 tmpfs, 或者用共享内存 shm_open(3)
    liuqhang
        5
    liuqhang  
       Apr 21, 2017
    用 redis 应该可以,如果只是想把数据放入内存的话。不是很明白你需求。
    mx1700
        6
    mx1700  
       Apr 21, 2017 via Android
    整个加载内存映射文件到内存估计也得几分钟,还是会停止服务
    yidinghe
        7
    yidinghe  
       Apr 21, 2017 via Android
    内存映射文件也那么大,读取也要耗时间吧。瓶颈在 IO 的话,最好想办法避免 IO 本身
    enenaaa
        8
    enenaaa  
       Apr 21, 2017
    可以考虑将数据从 mysql 迁移到 redis 上, 或用 redis 代替 B 。
    另外保证服务不挂逼更重要
    erobot
        9
    erobot  
       Apr 21, 2017
    感觉你需要的只是要避免 A 对外停止服务,如果内存够,那 A 多开一个线程读数据,读完了后切用新数据,把旧数据释放掉就好了
    erobot
        10
    erobot  
       Apr 21, 2017
    怕 A 读数据影响稳定的话, billlee 提到的共享内存也类似, B 把数据处理好后放内存,通知 A 切换使用新数据
    ryd994
        11
    ryd994  
       Apr 21, 2017
    “映射文件只读不修改” 那为什么不做个抽象层直接从数据库取数据?最多套个缓存
    willakira
        12
    willakira  
       Apr 21, 2017
    巧了,我们公司正好就是你这个 case ,但是 producer 有好几百台机器, consumer 在一万台以上,每天 deliver 的数据在 TB 级吧
    我们这么做的,以一个 producer 为例
    - producer 读取数据库,生成一个压缩的 snapshot
    - producer 分发种子给 consumer ,然后 consumer 通过 bittorrent 协议(私有云)下载 snapshot
    - consumer 定期直接加载到内存,只读,不 mmap 。

    周而复始
    bccber
        13
    bccber  
    OP
       Apr 21, 2017
    @ryd994 服务 A 从数据库取数据需要 6 分钟 通过服务 B 先生成文件 服务 A 再读取这个文件 只要三秒

    @erobot 如果服务 A 不挂逼 多开一个线程加载数据 是可以的 如果挂了 需要花 6 分钟加载数据

    @enenaaa redis 不合适 或者说没必要再用 redis 多加一层网络的消耗

    @willakira 是的 和你的做法是一样的 最后只是纠结于 直接把文件的内存加载到物理内存还是直接读取 mmap
    willakira
        14
    willakira  
       Apr 22, 2017
    加到内存就可以了

    mmap 主要用于进程间通信的文件共享
    mengzhuo
        15
    mengzhuo  
       Apr 22, 2017 via iPhone
    我就想问为什么要全部加载?
    julyclyde
        16
    julyclyde  
       Apr 22, 2017
    哈,和我们公司的做法一样
    不过我提示一点:加载文件过程期间还是不能服务的
    bccber
        17
    bccber  
    OP
       Apr 22, 2017
    @mengzhuo 因为内存够大

    @julyclyde 我是这样想的 加载文件 也使用 mmap 的方法加载 速度比 IO 快吧 全部加载到物理内存后 就抛弃 mmap
    julyclyde
        18
    julyclyde  
       Apr 22, 2017
    @bccber 总读入量并没节省啊
    mengzhuo
        19
    mengzhuo  
       Apr 24, 2017
    @bccber 内存够大的话, Linux 会把磁盘上的数据 cache 的,两者性能应该差别不大的。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   921 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 55ms · UTC 18:32 · PVG 02:32 · LAX 11:32 · JFK 14:32
    ♥ Do have faith in what you're doing.