V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
bccber
V2EX  ›  程序员

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

  •  
  •   bccber · 2017-04-20 23:29:46 +08:00 · 3394 次点击
    这是一个创建于 2772 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

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

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

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

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

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

    周而复始
    bccber
        13
    bccber  
    OP
       2017-04-21 14:54:46 +08:00
    @ryd994 服务 A 从数据库取数据需要 6 分钟 通过服务 B 先生成文件 服务 A 再读取这个文件 只要三秒

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

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

    @willakira 是的 和你的做法是一样的 最后只是纠结于 直接把文件的内存加载到物理内存还是直接读取 mmap
    willakira
        14
    willakira  
       2017-04-22 01:49:41 +08:00
    加到内存就可以了

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

    @julyclyde 我是这样想的 加载文件 也使用 mmap 的方法加载 速度比 IO 快吧 全部加载到物理内存后 就抛弃 mmap
    julyclyde
        18
    julyclyde  
       2017-04-22 18:59:52 +08:00
    @bccber 总读入量并没节省啊
    mengzhuo
        19
    mengzhuo  
       2017-04-24 16:43:12 +08:00
    @bccber 内存够大的话, Linux 会把磁盘上的数据 cache 的,两者性能应该差别不大的。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   968 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 20ms · UTC 21:36 · PVG 05:36 · LAX 13:36 · JFK 16:36
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.