请教如何高效实现从大量文本里随机读一行文字这样的任务? 希望充分利用内存 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
mfhh
V2EX    程序员

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

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

    • 挑战在于:
      文本库会随时增加.
      为了方便,增加文本库的时候就是上传文本文件.
      假设文本库非常大,可以上 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     Solana     3124 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 30ms UTC 12:30 PVG 20:30 LAX 05:30 JFK 08:30
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86