请支招: redis || mysql 评论,赞,星标,这些互动数据 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
whatisnew
V2EX    Redis

请支招: redis || mysql 评论,赞,星标,这些互动数据

  •  
  •   whatisnew 2015-05-06 08:38:34 +08:00 9216 次点击
    这是一个创建于 3812 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近遇上评论数据的瓶颈了,放 mysql 吧受不了这么大的请求量,放 redis 吧,内存受不了。

    mysql 请求太多,继续用的话只能再堆服务器了

    redis 吧,数据太多了,比如:评论数据item_comment:item_id 去存取数据的话,那么现在的 item 已经到6位数了。。。那么也就是说 redis 里有 item_comment:654321(n) 仅仅评论数据就有 6 位数的 key 了,那么加上所有的互动就有 5*654,321 位数的 key,还是继续增加中。。。内存就。。。。

    有什么好办法。。。

    61 条回复    2015-05-07 00:14:07 +08:00
    zhangwei
        1
    zhangwei  
       2015-05-06 08:45:32 +08:00
    又想马儿跑得快,又想马儿不吃草
    whatisnew
        2
    whatisnew  
    OP
       2015-05-06 08:46:13 +08:00
    以前老骂cnbeta只在24小时内显示评论数据,现在终于充分理解了。。。
    whatisnew
        3
    whatisnew  
    OP
       2015-05-06 08:47:35 +08:00
    @zhangwei 问题是老这和堆服务器,除了堆服务器,算法上有没有可能做一些优化呢。

    我们现在考虑用 ssd 纯文本存储评论数据。。。
    freshlhy
        4
    freshlhy  
       2015-05-06 08:48:37 +08:00
    围观
    zhangwei
        5
    zhangwei  
       2015-05-06 08:48:53 +08:00
    @whatisnew 内存价格其实还可以
    lzxgh621
        6
    lzxgh621  
       2015-05-06 08:54:36 +08:00
    @whatisnew 然后,我就在没去过cnbeta,没评论没意义。
    watisnew
        7
    whatisnew  
    OP
       2015-05-06 08:55:23 +08:00
    @lzxgh621 哈哈哈,我现在是只看个标题
    rqrq
        8
    rqrq  
       2015-05-06 08:56:23 +08:00
    业务需求是什么?以至于十万级的评论数据让mysql承受不了了。
    gowithwind
        9
    gowithwind  
       2015-05-06 08:57:37 +08:00
    舍不得内存,就用缓存呗.针对热数据缓存.
    whatisnew
        10
    whatisnew  
    OP
       2015-05-06 08:58:41 +08:00
    @rqrq 。。。数据容量不是问题,问题在连接数和IO
    whatisnew
        11
    whatisnew  
    OP
       2015-05-06 08:59:10 +08:00
    @gowithwind 热数据缓存不还得用到 redis 么。。。
    Livid
        12
    Livid  
    MOD
    PRO
       2015-05-06 09:00:21 +08:00   1
    数据库大到一定程度就必须要拆。

    拆到不同的表甚至不同的服务器上。
    nowcoder
        13
    nowcoder  
       2015-05-06 09:01:10 +08:00
    牛客网的评论放在mysql,赞放在redis
    simonlei
        14
    simonlei  
       2015-05-06 09:01:44 +08:00
    冷热数据分离热数据在内存,冷数据在硬盘。
    wy315700
        15
    wy315700  
       2015-05-06 09:03:10 +08:00
    mysql试试看innodb呗

    不行就上hbase吧
    xiaozi
        16
    xiaozi  
       2015-05-06 09:05:08 +08:00   1
    用hash优化

    item_comment:6543
    21(n)
    22(n)

    设置过期时间,自动清理冷数据
    kier
        17
    kier  
       2015-05-06 09:07:31 +08:00
    说说看并发量是多大?
    whatisnew
        18
    whatisnew  
    OP
       2015-05-06 09:08:16 +08:00
    设置过期时间是个好主意!
    但是 hash 优化的话。。。不在一个点上哦,一个 item_comment 对应的是一个 json 字符串,不是按多少楼分的。。。是依 item 为单位的。
    lincanbin
        19
    lincanbin  
       2015-05-06 09:09:37 +08:00
    评论的缓存过期时间是多久?
    whatisnew
        20
    whatisnew  
    OP
       2015-05-06 09:10:06 +08:00
    然后, item_comment 里对应的那些用户 user_id 读取 avatar nickname 这些字段怎么办。。。存成死数据吗?
    whatisnew
        21
    whatisnew  
    OP
       2015-05-06 09:11:00 +08:00
    @lincanbin 现在是30天,打算改到10天
    xiaozi
        22
    xiaozi  
       2015-05-06 09:12:04 +08:00
    @whatisnew redis的配置文件中 hash-max-ziplist-entries,会对 hash 存储进行优化;你把 key 的 id 拆分成两个数字,一个 hash 里面大概存 1000 个好了,每个子 id 也是对应一个字符串;如果觉得子 id 也长了,可以对子 id 进行 base62 转换。
    whatisnew
        23
    whatisnew  
    OP
       2015-05-06 09:14:47 +08:00
    @xiaozi 把 key 的 id 拆分成两个数字.... 这一段没看懂,哪个 key 哪个 id?一个 hash 里边可以存超过 6 位数的 field 吗。。。
    cdffh
        24
    cdffh  
       2015-05-06 09:17:12 +08:00
    十万条数据不断多哦 是读写太频繁了吗
    huitailang
        25
    huitailang  
       2015-05-06 09:18:38 +08:00
    围观~
    whatisnew
        26
    whatisnew  
    OP
       2015-05-06 09:19:06 +08:00
    @cdffh 这只是评论数据。。。还有很多其他数据
    cdffh
        27
    cdffh  
       2015-05-06 09:21:25 +08:00
    额 现在大概的数据规模是多大啊。 并发多少啊。这些情况要说清楚啊。不然不好找优化点啊
    gowithwind
        28
    gowithwind  
       2015-05-06 09:24:31 +08:00
    我看楼主也是不愿花钱,这样的话考虑用ssdb吧.和redis基本类似,底层是leveldb,大量数据存在硬盘里,性能也可以.
    xiaozi
        29
    xiaozi  
       2015-05-06 09:26:51 +08:00
    @whatisnew

    比如你是这样的:

    item_comment:6543001
    item_comment:6543002
    item_comment:6544010

    然后存成这样的:

    hset item_comment:6543 001 '这是json str'
    hset item_comment:6543 002 '这是json str'

    hset item_comment:6544 002 '这是json str'

    不是存成一个大hash,是好多个hash
    nevernet
        30
    nevernet  
       2015-05-06 09:29:05 +08:00
    @gowithwind ssdb现在稳定了吗?
    czheo
        31
    czheo  
       2015-05-06 09:29:19 +08:00
    mysql主从设了么?读写分离啊。
    whatisnew
        32
    whatisnew  
    OP
       2015-05-06 09:35:48 +08:00
    @czheo 主从,读读读写分离,主从从从 这都是标配了。。。
    whatisnew
        33
    whatisnew  
    OP
       2015-05-06 09:36:39 +08:00
    @nevernet 我看了 ssdb 的文档,看了半天也没看出来他是存在内存还是ssd
    lincanbin
        34
    lincanbin  
       2015-05-06 09:40:53 +08:00 via Android
    @whatisnew 需要缓存的只是热数据,你设置1天都够多了。
    czheo
        35
    czheo  
       2015-05-06 09:47:54 +08:00
    mysql query cache开了么?
    whatisnew
        36
    whatisnew  
    OP
       2015-05-06 09:48:48 +08:00
    @lincanbin 那不是跟 cnbeta 一样了。。。很多人喜欢评论的
    whatisnew
        37
    whatisnew  
    OP
       2015-05-06 09:51:07 +08:00
    @czheo 这个。。。 cache 是在应用层做的,不是在 mysql
    youxiachai
        38
    youxiachai  
       2015-05-06 09:54:26 +08:00
    ssdb ? 接口跟redis 直接兼容..
    czheo
        39
    czheo  
       2015-05-06 09:55:29 +08:00
    redis里面放最近1000的comment, 翻页到1000以后开始从mysql读数据。
    whatisnew
        40
    whatisnew  
    OP
       2015-05-06 09:56:05 +08:00
    @youxiachai 我是说他是存内存的还是存ssd的。。。还是都可以。。。
    justfly
        41
    justfly  
       2015-05-06 09:56:17 +08:00
    给个思路 mysql里面放评论的详细信息 redis里面只存放 ID 查询的时候先查redis得到ID 再从mysql里面拿详细信息组合 mysql上面可以放一层memcache或者redis 固定内存大小 做缓存 存放热数据
    tonghuashuai
        42
    tonghuashuai  
       2015-05-06 10:19:19 +08:00
    如果是我我会这么做:
    评论内容放在 mysql,评论关联,赞,星标放到 redis
    tonghuashuai
        43
    tonghuashuai  
       2015-05-06 10:29:20 +08:00
    抱歉,上一条回错了,没有看全就回了。。。
    tonghuashuai
        44
    tonghuashuai  
       2015-05-06 10:40:24 +08:00
    我会这么做:
    * 评论内容存到 mysql 中,比如 comment_id, txt
    * 评论的关联存在 redis 中,用 zset(score为评论时间戳方便排序),sadd item_comment:item_id score comment_id
    也就是 redis 中只有 id,都是 int 占用应该不会太过分吧,查询时查 redis 获取某个文章的评论id及排序,然后根据查到的 id 去 mysql 中查评论内容 (建好索引什么的应该不会慢吧)。
    如果 id 增长很快的话可以用上面说的做一下 base64或MD5 就定长了
    这样的话,只有有评论的文章才会在 redis 中有记录。

    星标和攒就类似了,只有 id 关联,全在 redis 中,可以参考新浪微博的关注的实现。
    cfan8
        45
    cfan8  
       2015-05-06 10:52:42 +08:00
    评论数据直接和item meta info压在一起吧,既然上NoSQL也没必要考虑什么范式之类的东西了
    guoer
        46
    guoer  
       2015-05-06 11:16:01 +08:00
    http://opentalk.upyun.com/show/issue/15
    这里面洪小军的演讲可能对你有帮助
    fuxkcsdn
        47
    fuxkcsdn  
       2015-05-06 11:20:32 +08:00
    把最近1礼拜的评论存放在 redis 上,其余的存在 mysql 里,1礼拜前的老帖本来看的人就少(你去试试要翻 cnbeta 1礼拜前的贴要翻几页就知道了)

    代码里也就多一个判断
    $comment = hGetAll('item_comment:65442345');
    if(count($comment) === 0) {
    $comment = $pdo->query('select * from t_comment where id=65442345');
    }
    yuankui
        48
    yuankui  
       2015-05-06 11:29:42 +08:00
    yuankui
        49
    yuankui  
       2015-05-06 11:31:38 +08:00
    评论的化,放 mysql,加上索引,性能问题应该不大吧,而且,可以加缓存啊.
    fenzlie
        50
    fenzlie  
       2015-05-06 12:13:59 +08:00   15
    为了回答这个问题特意去注册了一个帐号,结果发现还得等7000秒才能回复...

    首先,如果你的系统还没有一个DAL层,那么是时候去实现一个了。否则下面的内容也没必要看了。

    短期解决方案,你的MYSQL使用肯定有问题,不到百万级的数据不太可能搞不定。从表结构,语句,配置,连接池等等方面入手优化。就算你的业务再复杂,应该也可以应付得来。如果实在不行,必须要用REDIS,那就自己写一个一致性HASH,REDIS设置成多节点负载。这个实现快,也十分有效果,从KEY的数量上来看,区区65万X5也不算很大。 我之前记得100万KEY在REDIS中使用的内存也不过70M这样而已,当然,这和存的VALUE也有关系。现在商用服务器随便32G 64G内存,对数据结构做一些优化,REDIS也作一些优化BLABLA,用REDIS存储完全没有压力。注意这个阶段因为是对REDIS直接当数据库用的,所以要特别注意它的数据持久化和恢复方案。

    如果从预期上来看数据会随业务发展有暴发式增长的话,那就需要考虑冷热数据交替的架构,简单讲就是加缓存结构,其它分库分表之类的就不提了。 可以把上述短期解决方案中的REDIS集群直接用做缓存,不会改变的冷数据扔到MYSQL数据库中去。请求先到缓存层,取不到再到数据库去取,同时把数据放置在REDIS中。这里大概的实现可以这样做,所有在REDIS中的数据全都设置相应的过期时间,每次访问重置过期时间。在每个REDIS MASTER节点拖的SLAVE节点上作RDB,把生成的RDB文件离线定时解析,把其中过期时间小于某值的所有数据同步到MYSQL中。

    终极解决方案,如果你的数据量和访问量大到没边了。以上的REDIS集群不管怎么扩容,连正常的查询修改操作也完全COVER不住时。首先要恭喜你的应用比较牛B了现在。现在要做的事情有很多,可能需要有多级缓存,CDN扩展,甚至业务上要作一些妥协等等。从框架上来讲,大概的思路就是读写分离以及深化分离。 比如说,你前两步做的REDIS集群只用作读操作了,所有写操作只记录在简要日志中。写操作的请求过程中,不在数据持久层或缓存层作修改操作。然后你有离线的系统TAIL所有写操作的简要日志,把这些操作离线同步到数据持久层和缓存层。不过这样写操作因为只是记录了日志,写操作完成后有一段时间查询请求过来时是访问不到该修改的。这段时间的长短与你的离线日志流处理系统的性能相关。

    REDIS 的RDB解析可以用RDIS RDB TOOLS, 用PYTHON写的,对过期时间的处理可能需要一些自定义的修改,PYTHON新手就可以胜任。
    日志流的处理可以用卡夫卡,可靠,安全,速度快。
    north521
        51
    north521  
       2015-05-06 12:19:27 +08:00
    @fenzlie 讲得很好啊
    sunchen
        52
    sunchen  
       2015-05-06 12:21:46 +08:00
    试试aerospike,使用ssd
    keakon
        53
    keakon  
       2015-05-06 12:32:34 +08:00
    粗略看了下,只有 @xiaozi 说的是能快速有效解决的,很多人不用勉强答的…
    zyue
        54
    zyue  
       2015-05-06 12:36:14 +08:00
    @fenzlie 赞一个 讲的很好
    daoluan
        55
    daoluan  
       2015-05-06 13:01:45 +08:00
    只缓存热数据,数据库做分表/库,redis 没有你想的那么弱。
    phx13ye
        56
    phx13ye  
       2015-05-06 13:13:28 +08:00
    @fenzlie
    没有体验过这种场景,有专门讲方面的书吗???
    jevonszmx
        57
    jevonszmx  
       2015-05-06 13:47:25 +08:00   1
    @fuxkcsdn

    hgetall,时间复杂度是O(N),会死的很惨,慎用。



    应该分几个方面处理啊:
    1、分析用户常见浏览量,如果大多数浏览量都是最近N条,则做评论翻页功能,最新N条是热数据,存redis,其他可以使用mysql做被动缓存;

    2、评论分页使用前端缓存,如varnish,这样可以大大减轻后端压力;

    3、mysql数据分表;

    4、redis拆分实例,我们是程序实现了一个redis切片集群,通过key名hash切分到不同的redis实例;
    wys163
        58
    wys163  
       2015-05-06 14:21:25 +08:00
    mongodb 拯救你
    fenzlie
        59
    fenzlie  
       2015-05-06 15:42:00 +08:00   1
    @phx13ye 倒是没有留意过专门写这种场景的书。我是这样的来的,先了解一些分布式系统的基础知识,再找一些淘宝,京东,新浪微博等相关的讲座或说明去了解下。参加一些技术分享会,理解一些分布式相关的开源项目实现,比如说ZOOKEEPER,SPARK等。主要是理解这些公司分别应对的是什么样的问题,再去比较它们之间相似系统的实现差别。当然,最好是能进入有大流量公司的研发部门,这样直接干这一行最有效。

    这些问题大多是有些难度,又十分有意思,实现了又很有成就感的。比如说淘宝双11时在一个电视上实时的秒级同步显示当前各地区交易总量,交易总额。这个东西正常人都知道肯定不可能是每秒执行一个SQL去数据库里查出来的。
    hanwujibaby
        60
    hanwujibaby  
       2015-05-06 18:34:22 +08:00
    没有必要把所有的值放到缓存里。热数据放到缓存中,每次写的时候同步更新缓存的失效时间。redis活memcache有自己的缓存失效算法的。如果用redis的话, 注意redis的slave.不然主挂掉的话,缓存雪崩很麻烦。大并发下能直接压死mysql.大数据的话注意一下分表和分库。这些基本的策略能扛住日均1亿的访问。
    gfreezy
        61
    gfreezy  
       2015-05-07 00:14:07 +08:00
    qps到多少了,MySQL机器的配置是什么?
    我们业务 “赞” 的表到千万量级,用MySQL完全没啥问题啊。

    之前是遇到过MySQL性能不够用,后来升级了下MySQL的机器,问题就解决了。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2636 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 06:29 PVG 14:29 LAX 23:29 JFK 02:29
    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