如何取出大数据量的 redis hash 结构的数据并遍历导出? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
tanteng
V2EX    Redis

如何取出大数据量的 redis hash 结构的数据并遍历导出?

  •  
  •   tanteng
    tanteng 2016-03-01 12:04:56 +08:00 28687 次点击
    这是一个创建于 3590 天前的主题,其中的信息可能已经有所发展或是发生改变。

    redis hgetall

    如图,存了一个 hash 结构的数据, key 是用户名, value 是这个用户的一些信息,这个 hash 结构的数据会增长,最后数据量可能非常大。

    假如用 hgetall 一次取出所有数据,然后去遍历导出,大数据的情况可能会: 1.影响其他 redis 的操作 2.内存溢出

    需求是把这个 hash 结构的数据导出,比如导出到数据表或者 excel 文件。

    有什么好的技术实现方法?谢谢!(程序语言 PHP , JAVA , Python 都可以)

    26 条回复    2016-04-14 18:55:06 +08:00
    yuankui
        1
    yuankui  
       2016-03-01 12:48:15 +08:00   1
    一定是设计出了问题
    soli
        2
    soli  
       2016-03-01 13:00:09 +08:00   2
    你需要的是 HSCAN : http://redisdoc.com/hash/hscan.html
    tanteng
        3
    tanteng  
    OP
       2016-03-01 13:05:28 +08:00
    @yuankui 那像这种一开始没有记录到数据库,直接存到 redis 的数据,如何导出呢
    Jaylee
        4
    Jaylee  
       2016-03-01 13:07:26 +08:00   1
    先 keys * 取所有 key , 然后遍历
    tanteng
        5
    tanteng  
    OP
       2016-03-01 13:10:56 +08:00
    @Jaylee 先 hkeys key ,然后根据这个 key 去遍历取 hash 的数据?? 1.这个 keys 可能非常大有没有影响 2.这样会大大增加操作 redis 的次数,是不是问题
    Jaylee
        6
    Jaylee  
       2016-03-01 13:28:38 +08:00   1
    @tanteng 1, 没有影响 2.不是问题
    zhs227
        7
    zhs227  
       2016-03-01 13:37:34 +08:00   1
    @tanteng Redis 官方原来有个加密的功能,但是官方说你们不应该太相信这个功能,因为 Redis 的存取速度太快了,破解起来飞起。

    http://redis.io/commands/AUTH

    Note: because of the high performance nature of Redis, it is possible to try a lot of passwords in parallel in very short time, so make sure to generate a strong and very long password so that this attack is infeasible.

    高速存取是 Redis 的优势,操作次数根本不是问题。
    kingddc314
        8
    kingddc314  
       2016-03-01 13:41:17 +08:00
    可以使用 redis 内的 lua 脚本进行处理
    EVAL script numkeys key [key ...] arg [arg ...]
    kingddc314
        9
    kingddc314  
       2016-03-01 13:43:20 +08:00   1
    可能理解错了楼主的意思,同 2L ,你需要的应该是 HSCAN 进行遍历
    tanteng
        10
    tanteng  
    OP
       2016-03-01 14:13:25 +08:00
    @kingddc314 hscan 只支持 2.8 以上版本
    ynztyl10
        11
    ynztyl10  
       2016-03-01 14:28:55 +08:00
    keys * 确认没问题?不要误导。。
    fwrq41251
        12
    fwrq41251  
       2016-03-01 14:33:21 +08:00
    像这种情况一般还会有个 set 存所有用户的用户名吧。这样直接取这个 set,再根据 key 遍历就好了。
    zts1993
        13
    zts1993  
       2016-03-01 14:40:42 +08:00
    hscan 啊。。。。。
    tanteng
        14
    tanteng  
    OP
       2016-03-01 15:47:26 +08:00
    @fwrq41251 并没有
    rubytek
        15
    rubytek  
       2016-03-01 17:30:01 +08:00
    @tanteng 是说设计成自带一个 Key 的集合啊。
    tanteng
        16
    tanteng  
    OP
       2016-03-01 17:33:49 +08:00
    从集合中取出所有用户 id ,和从 hash 中通过 hkeys 取,有什么不同吗
    tanteng
        17
    tanteng  
    OP
       2016-03-01 17:33:58 +08:00
    @rubytek 从集合中取出所有用户 id ,和从 hash 中通过 hkeys 取,有什么不同吗
    neoblackcap
        18
    neoblackcap  
       2016-03-01 18:02:52 +08:00   1
    @tanteng 一个是全部读到你 Client 端的内存里面,在 Client 端以一个数据结构或者对象的形式存在。一个只是一个迭代器。
    简单而言,内存消耗不一样。
    soli
        19
    soli  
       2016-03-01 18:14:55 +08:00   1
    KEYS 、 HGETALL 等命令应禁止在生产环境使用。看官方文档,都有非常显眼的警告。
    tanteng
        20
    tanteng  
    OP
       2016-03-01 18:32:42 +08:00
    @neoblackcap 这个明白,但是要 2.8 才支持 hscan
    tanteng
        21
    tanteng  
    OP
       2016-03-01 18:33:04 +08:00
    @soli 看来不能用这种方式
    solaro
        22
    solaro  
       2016-03-09 11:16:35 +08:00
    @Jaylee 你这种做法就是要坑死楼主的, keys * 在生产环境里我都是禁用的,量大的时候秒蹦你缓存你信不信,执行一次得卡上 N 秒或者 N 十秒
    tanteng
        23
    tanteng  
    OP
       2016-03-09 11:18:16 +08:00
    @solaro 还没着手做这个,用 hscan 是否可行?
    solaro
        24
    solaro  
       2016-03-09 11:22:23 +08:00
    如果是我,我会这么做:
    1.一个 hash , hash-key :uid, hash-value:zsetid_uid
    2.一个 zset, id:uid ,value : user info
    各种好判断, hash 效率高,单量小, zset 可以用来分页,分段取出
    甚至你存储的时候可以做 shard
    solaro
        25
    solaro  
       2016-03-09 11:23:36 +08:00
    如果 hash 丢了,重建结构简单,
    如果 zset 丢了,重建,也不难。
    当然,你那个 hash 其实从业务上来说是最简单的
    abc123ccc
        26
    abc123ccc  
       2016-04-14 18:55:06 +08:00
    @tanteng 建议:
    方案 1 、凌晨某个点,一次 hgetall 把 key 写入到队列当中,这样你的队列与 hash 就能保持一致了,以后取数据就相当的容易。因为 list 里的值就为 hash 的 key 。但可以告诉你的是:一次性读入大量的数据,整个网站都会很慢。

    方案 2 、如果你的 hash 的 key 是有规律的,那就写个程序往 list 里赛吧,定时定量跑。跑完为止。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5404 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 07:56 PVG 15:56 LAX 23:56 JFK 02:56
    Do have faith in what you're doing.
    ubao msn 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