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

请教如何高效实现从大量文本里随机读一行文字这样的任务? 希望充分利用内存

  •  
  •   mfhh · 2015-09-21 07:31:06 +08:00 · 3408 次点击
    这是一个创建于 3353 天前的主题,其中的信息可能已经有所发展或是发生改变。
    • 想做一个这么一个东西:
      有一堆纯文本文件,小说之类的.
      随机的挑一个小说,随机的挑一段,随机的挑一句.
      呈现这一句.
      如果读者感兴趣,再打开这一段.更感兴趣,再看全文.

    • 挑战在于:
      文本库会随时增加.
      为了方便,增加文本库的时候就是上传文本文件.
      假设文本库非常大,可以上 T.
      如果每次都从磁盘读取文件,没有充分利用内存.

    • 那么希望有个自动的缓存策略.不知道有什么框架或者工具可以用?

    13 条回复    2015-09-22 16:40:35 +08:00
    Andiry
        1
    Andiry  
       2015-09-21 07:54:27 +08:00
    Redis
    zado
        2
    zado  
       2015-09-21 07:57:56 +08:00
    反正都是随机的,你可以预先随机读取一大批集中存放一个文件里,以后每次都是读取这个文件。
    mfhh
        3
    mfhh  
    OP
       2015-09-21 08:09:22 +08:00
    @Andiry 谢谢.我也刚刚想到. 以前有 redis 只存储小的键值对. 有点思维定势了. redis 好像有个 diskstore?
    mfhh
        4
    mfhh  
    OP
       2015-09-21 08:10:38 +08:00
    @Andiry redis 对 value 的大小有限制么?
    maddemon
        5
    maddemon  
       2015-09-21 08:47:26 +08:00
    可以这样吗?
    缓存所有小说的文本的行数,需要展现哪一行就读取哪一行。
    因为这个需求随机性太大,不可能缓存所有的小说,某一行被读取过,再次展现的时候如果还会展现这段话(维持一定时间)可以还存下来这行,否则每次随机的话,这一行就应该被废弃。

    如果能够预先知道需要展现哪部小说,可以预先缓存这部小说。
    LeonT
        6
    LeonT  
       2015-09-21 09:01:14 +08:00   ❤️ 1
    性能主要是消耗在寻找文件上面,所以,将文件以及文件大小的列表存放在内存里面,需要的时候随机选择一个文件(根据大小加权随机,这样的话大的文件选择的概率会高,因为行数多),然后直接去硬盘随机读取一块数据(用 seek 调用,读取 4K ,一般就是块大小),把里面的完整的一行取出来就行了吧。

    如果磁盘读取的时候某个块读取的多,然后内存够大,操作系统会自动做缓存的。
    pichina
        7
    pichina  
       2015-09-21 13:50:54 +08:00
    利用倒排索引,建立全文索引。 你的任务跟搜索引擎一样一样的。
    pichina
        8
    pichina  
       2015-09-21 13:53:50 +08:00
    对内存利用可以有查询缓存,这都是搜索引擎干过的活儿。
    CYKun
        9
    CYKun  
       2015-09-21 20:59:59 +08:00
    我觉得你需要 MongoDB
    mengzhuo
        10
    mengzhuo  
       2015-09-21 22:00:49 +08:00
    很简单,连数据库都不需要啊!!!

    直接按上传的文件 hash 出一个值,保存一个索引文件 map[文件 hash]行数 在磁盘上

    这时应该长这样
    ------index
    |---00/....
    |---01/....


    (火狐就是这么实现 cache 的)

    按随机数出一个文件,再随机出一行
    有概率出一段

    然后读取并返回
    soratadori
        11
    soratadori  
       2015-09-22 00:00:39 +08:00
    你可以做一个伪随机,然后预先缓存这部分.............
    pichina
        12
    pichina  
       2015-09-22 11:06:48 +08:00
    @mengzhuo 这种做法就是倒排索引。参考 lucene
    mfhh
        13
    mfhh  
    OP
       2015-09-22 16:40:35 +08:00
    谢谢大家. 先做了个原型
    http://one.treenote.net/

    其实随机的要求没有很高. 所以差不多的办法都可以. 考虑的重点是作为 web 应用,不希望每次请求都要读硬盘. 我初步考虑的方案是做 2 重随机. 一个慢随机,是每累积多少次访问就去磁盘随机 load 一些大内容块到内存中. 一个快随机,每次请求都从内存中随机的取出小内容块.
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4127 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 05:24 · PVG 13:24 · LAX 21:24 · JFK 00:24
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.