关于 redis 的储存问题。 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
mandy0119
V2EX    Redis

关于 redis 的储存问题。

  •  1
     
  •   mandy0119 2018-04-08 16:42:55 +08:00 6599 次点击
    这是一个创建于 2744 天前的主题,其中的信息可能已经有所发展或是发生改变。

    有很大量用户信息,需要放进缓存中。

     方法 1:每个用户一个 key,单独存放。 方法 2:所有用户存入一个 key,类型为 hash。使用时取出此 hash,再操作。 

    目前有点拿不准该用哪一种效率高一些,资源利用率高一些。

     讨论:数据量 N 大于何值时,方法效率最高。 讨论:何种场景,使用方法 1/2 比较合适。 

    对 redis 理解不深,求大佬们解疑。

    第 1 条附言    2018-04-08 18:57:50 +08:00
    感谢各位的解惑。我在这总结一下:
    总体来说,方法 1 更优。
    方法 1:
    优点:1. 粒度更细;
    2. 避免很多后期优化问题,一步到位;
    3. 避免很多方法 2 存在的问题(不重复罗列)。
    缺点:1. 做好 key 的回收机制;
    2. 内存使用率略低于方法 2 ;
    3. 同类型数据的 key 在 redis 中非常分散

    方法 2:
    优点:1. 内存使用率高(当 value 为 int 会被压缩,甚至可以压缩到 1/10 ) from #21
    2. 相对 而言较适合长期储存用户
    3. 千级数据以下优势较明显
    缺点:1. 所有数据保存在一个 key 中,单 key 长度不可控,在集群中优化困难;
    2. 方法 1 中不同用户可以被存在集群不同机器内;
    3. 单个 key 安全性差,崩了就全完了;
    4. 单 key 数据过大,传输耗时也存在问题;

    从时间性能以及安全性来看,都是方法 1 比较好。
    另感谢#5 给出的链接 http://carlosfu.iteye.com/blog/2254572
    里面是美团的解决方案

    方法 3:
    将所有用户进行分段( all/100 ), 然后利用方法 2 储存。
    分段方法就不赘述了,可以通过 userid 等。内存利用率非常可观。
    26 条回复    2018-04-09 01:40:51 +08:00
    Immortal
        1
    Immortal  
       2018-04-08 16:47:26 +08:00
    具体没测试过,单纯从以前看过的 redis 的优化文章来看
    方法 2 资源(内存)利用率高很多,方法 1 中虽然是 kv 结构,但是就算是最简单的 kv,对于 redis 的数据结构也有很多额外数据
    undefinedMe
        2
    undefinedMe  
       2018-04-08 16:52:20 +08:00
    方法一
    defunct9
        3
    defunct9  
       2018-04-08 16:56:36 +08:00
    方法二
    rrfeng
        4
    rrfeng  
       2018-04-08 16:59:39 +08:00 via Android
    任何情况下都应该用 1
    单 key 太大是一个非常大的隐患
    micean
        5
    micean  
       2018-04-08 16:59:53 +08:00   4
    lastpass
        6
    lastpass  
       2018-04-08 17:02:38 +08:00 via Android   1
    方法一吧。毕竟你这是不是大量用户,而是很大量用户。
    用方法二,取所有用户这个数据,仅仅是数据传输都要一定的时间。
    jelinet
        7
    jelinet  
       2018-04-08 17:04:14 +08:00
    方法 1 吧。
    lastpass
        8
    lastpass  
       2018-04-08 17:05:18 +08:00 via Android   1
    而且,用方法二,你对用户信息的增删改等操作也很麻烦。容易出错。而且方法二将所有鸡蛋放在同一个篮子里。一旦这个数据发生点意外情况。你所有用户数据全部 gg。
    xomix
        9
    xomix  
       2018-04-08 17:07:24 +08:00   1
    数据量在千级以下的时候方法 2 都是比较优秀的,当数据量超过千的级别,你获取全部用户信息的 value 传输都是个大问题。

    千级别以下我觉得基本上也用不上这些缓存了,你随便写个文本库都可以对应,所以你就不要想方法 2 了。
    nowgoo
        10
    nowgoo  
       2018-04-08 17:13:22 +08:00   1
    方案一。
    1. 可制定细粒度的缓存过期策略,更灵活。
    2. 用 mget/mset 读写。
    3. 如果每个 value 的长度都差不多,内存利用率应该还可以的。实在不行启用压缩嘛。
    myyou
        11
    myyou  
       2018-04-08 17:13:26 +08:00   1
    方法二效率最高,可用在长期缓存用户信息(只在用户更新用户信息时更新 hash field 的 value )
    方法一虽然内存使用率低,但是可以设置过期时间,对比不常登录用户可以避免占用内存

    方法一和二除了能对每个用户设置过期时间,其实没什么区别
    myyou
        12
    myyou  
       2018-04-08 17:14:52 +08:00
    @< href="/member/myyou">myyou 说错了,方法一内存占用更高
    Immortal
        13
    Immortal  
       2018-04-08 17:15:03 +08:00   1
    再多说一句 具体还得看你的 value 大小 这个也比较关键
    yang2yang
        14
    yang2yang  
       2018-04-08 17:43:22 +08:00   1
    用方法一吧,方法二导致 value 变大,会导致速度变慢的,内存利用率不是关键吧,一般都考虑时间吧?
    tusj
        15
    tusj  
       2018-04-08 17:53:54 +08:00
    方法 1 吧。
    R18
        16
    R18  
       2018-04-08 17:58:38 +08:00 via Android
    自己做下测试?
    tusj
        17
    tusj  
       2018-04-08 17:59:05 +08:00   1
    方法一好。
    因为如果以后要上 redis 集群的话,这些 key 可以分散到不同的主机以分摊压力。
    如果用方法二,所有数据都在一个 key 下,出现单点性能问题的话,就算上 redis 集群也没用。
    R18
        18
    R18  
       2018-04-08 17:59:27 +08:00 via Android
    如果使用方案一,如果用户真的很大,请设置 key 的自动过期或者回收机制
    hustlibraco
        19
    hustlibraco  
       2018-04-08 18:00:20 +08:00   1
    方法 1 可用,方法 2 数据量上来了不可控。
    在少量数据规模的时候方法二确实利用更高效,但是一般情况下不需要这么节省 redis 资源,方法一的扩展性更好,控制粒度也更细,一开始就用方法一没有后顾之忧
    catinred
        20
    catinred  
       2018-04-08 18:01:17 +08:00   1
    要单独对部分用户设置过期时间 那就方法 1
    要是单个用户的数据量比较小 例如几 K,那就方法 2
    主要还是看业务场景
    无论哪种方法,都尽量避免取所有用户数据。
    monsterxx03
        21
    monsterxx03  
       2018-04-08 18:01:46 +08:00   1
    从业务上看,用方法一.

    hash 的确能减少内存使用, 但有些前提. 因为 size 小于阈值的 hash 内部会用 ziplist 实现,如果 value 是 int,还会用特殊算法进行压缩,极端情况下内存占用可以减少到 1/10, 相关配置: hash-max-ziplist-entries, hash-max-ziplist-value


    https://redis.io/topics/memory-optimization
    banksiae
        22
    banksiae  
       2018-04-08 18:07:23 +08:00   1
    方法 1, 但是 key 的规则要定义清除,以免滥用
    单 key 值过大的话,如果要导入到 codis 集群,会遇到大小限制问题
    WinMain
        23
    WinMain  
       2018-04-08 18:41:19 +08:00   1
    还有折中的方法,对用户 id 取模后作为 key 来分桶,哈哈,个人之见,没试过。
    生产线上用的还是一个用户 id 一个 key,因为即使是有几十个亿的用户量,也不是把所有 id 的相关信息放入 redis,要不然就失去了作为缓存这个出发点了,每天最多也就是亿级的活跃用户,这个对于 redis 集群来说,都是小 ks。
    MeteorCat
        24
    MeteorCat  
       2018-04-08 19:06:18 +08:00 via Android
    看存储之后是否要频繁更新,我们游戏架构是 MYSQL 存储基本充值数额等外部信息,NoSQL 做游戏库,人物角色信息用 Hash 表保存便于读写和单独取出;但是如果仅仅做缓存,根据 key 找到用户信息不做大修改,我感觉直接 key-value 就行了
    wplct
        25
    wplct  
       2018-04-08 21:25:44 +08:00
    方法 1.未来可以直接上集群。
    qi1070445109
        26
    qi1070445109  
      2018-04-09 01:40:51 +08:00 via Android
    请教一下,如果用来做布隆过滤器呢?大家怎么选择? 目前是方法二。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     883 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 19:17 PVG 03:17 LAX 12:17 JFK 15:17
    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