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

Redis中保存好友关系,用list还是用set?

  •  
  •   yibin001 · 2013-01-18 09:18:52 +08:00 · 23041 次点击
    这是一个创建于 4108 天前的主题,其中的信息可能已经有所发展或是发生改变。
    现在维护一个项目,先说说数据库的情况:
    生产环境的用户量(用户表)为:1700W。
    用户的关注、好友在Friends表中,记录数为:3600W,现在每天的增长量为30W左右。
    id --主键,自增长
    userid --用户ID
    username --用户名 (冗余)
    targetuserid --对方用户id
    targetusername --对方用户名
    friendtype --是否为好友



    现在考虑对friends表做拆分,我的方法是按二个维度做拆分,也是通用做法:分成关注表与粉丝表,再对关注与粉丝做水平拆分。
    这意味着:二个人的相互关注,会产生4条记录,记录数会比单独的friends表要多,但这样拆分会换来效率上的提升,这还是值得的。


    最终大家还是觉得只对friends表做水平拆分,按userid区间分表,这样可以最大力度保持原表结构及原有的业务逻辑。
    但这样会带来新的问题:即无法按targetuserid查找粉丝。


    现在想把关注与粉丝放到Redis中,但似乎list/set都无法完全满足需求:
    set可以去重,但无法用原生命令取某一区间的值(体现在分页上)。
    list无法去重,但可以取某一区间,但同时,list也无法删除指定的value(比如取消对某一用户的关注)


    对于分表目前来说是对friends表水平拆分,这个基本确定了,但Redis这一块有什么好办法?新浪微博也是用的Redis维护关系,它们是怎么做到的?
    12 条回复    1970-01-01 08:00:00 +08:00
    wwwjfy
        1
    wwwjfy  
       2013-01-18 10:14:52 +08:00
    Sorted Sets?
    yibin001
        2
    yibin001  
    OP
       2013-01-18 10:31:42 +08:00
    @wwwjfy
    性能上,Sorted Sets与list/set差异大吗?像关注列表还好办,每个人的关注数是有限制的。
    但粉丝列表就有点夸张了,这个地方还没有完全想好怎么存粉丝。初步的粉丝存法呢,只保存1000个,1000个之后的直接DB了,况且这样的需求并不常见。
    linnchord
        3
    linnchord  
       2013-01-18 10:50:35 +08:00
    好友粉丝列表一般要按关系建立时间点排序吧?还是sorted好,粉丝一般排个5页就ok吧———数据分页大多数时候是个伪需求。
    wwwjfy
        4
    wwwjfy  
       2013-01-18 11:24:58 +08:00
    @yibin001 搜了下,看到新浪也说了,大数据量,redis做存储已经不太合适。虽然没说原因,但是内存太贵了。

    是不是可以数据库做存储,redis只做cache,去重在数据库完成,redis可以只用list,设置过期时间,只存储活跃用户的数据,内存就用不了太多
    xcl3721
        5
    xcl3721  
       2013-01-18 11:56:47 +08:00
    微博用的hset
    yibin001
        6
    yibin001  
    OP
       2013-01-18 12:04:52 +08:00
    @linnchord
    哈哈~看到高兄出没。分页呢有2种排序方式:关系建立时间点和最后登录时间。

    @wwwjfy
    这是一个方案,设想每一个list做一个过期时间,比如7天,每个list最多只放1000个用户(排好序的),设置一下list-max-ziplist-entries,压缩一下,估计内存上会节省不好。
    当然,不可能一次性把1700W用户都加载到内存,这里只做被动加载,Redis最多也只是当一个cache用。


    @xcl3721
    hset?hash?
    TerranC
        7
    TerranC  
       2013-01-18 12:07:32 +08:00
    其实可以在前端代码逻辑里去cache
    用户时常产生交互的人也就那么多
    list cache一份常用关系到redis
    qiongqi
        8
    qiongqi  
       2013-01-18 12:50:44 +08:00
    通常来说,zset会好些,各种操作的时间复杂度,占用cpu都好过list
    miizoo
        9
    miizoo  
       2013-01-18 17:37:42 +08:00
    如果列表也从redis中取的话,sorted set.
    仅仅关系的话,set。
    因为这样就可以用交集来看共同的好友,或是快速看是否关注了,或是看有多少个粉丝之类。
    yibin001
        10
    yibin001  
    OP
       2013-01-18 18:01:24 +08:00
    @miizoo
    对于分页这样的伪命题只能无视了。。。。
    单单从粉丝列表/关注列来说来,set是不是错的选择,遇到一种叫“排序”的需求,就麻烦了。
    比如按被关注人的上次登录时间排序。。。。。。
    darklowly
        11
    darklowly  
       2013-01-19 02:16:36 +08:00
    elasticsearch+cache瞬间搞定
    xatest
        12
    xatest  
       2013-01-19 19:11:17 +08:00 via iPhone
    Redis的sorted set 可以同时满足取区间值和删除指定值的需求,性能上与list, set相比主要是增删操作要慢一点,list增加一个元素是O(1)的,sorted set是O(log(n))级别,假如在每个用户的好友数据量不超过1000的情况下,也就是不超过O(10)的时间复杂度,可以接受。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2731 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 223ms · UTC 15:42 · PVG 23:42 · LAX 08:42 · JFK 11:42
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.