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

初入 Redis 向各位大神讨一个解决方案

  •  
  •   jsonfork · 2016-06-13 01:12:00 +08:00 · 3903 次点击
    这是一个创建于 3084 天前的主题,其中的信息可能已经有所发展或是发生改变。

    HTML 列表页面每条信息有一个顶、踩数的显示,这个要求显示实时,现在的实现是 HTML 加载完成,发送一个 ajax 到 PHP 然后 PHP 根据发送过来的 catid(栏目 ID) 和 ids(多条信息 id),来查表取信息中的顶、踩数。现在这样给数据库的压力比较大,想用一个中间层作为缓冲。 这个顶踩数用户可以点击,点击一次+1 ,每天只能点一次。

    请求数据过来时参数是这样: catid=1 ids=1,2,4,5,6 :查栏目 id 等于 1 下的信息 id 为 1,2,3,4,5,6 的顶踩数 。 返回数据: { "1":{"like":10,"hate":1}, "2":{"like":66,"hate":10}, "3":{"like":238,"hate":90}, "4":{"like":100,"hate":11} }

    1.点击顶踩数时做一个延时写入数据库,到一定量时才写入到数据。 2.这种结构怎么存储到 redis 里比较合理,栏目有很多。

    各位大神给支个招!!

    12 条回复    2016-06-14 16:26:39 +08:00
    Mirana
        1
    Mirana  
       2016-06-13 02:43:20 +08:00
    可以用一个 hset,key 是 catid,value 是 json 序列化的 string
    jsonfork
        2
    jsonfork  
    OP
       2016-06-13 08:19:44 +08:00 via Android
    @Mirana 那如果修改某个值不是还要序列化和反序列化吗。有点麻烦。
    tonghuashuai
        3
    tonghuashuai  
       2016-06-13 08:39:49 +08:00
    第一种: hset , catid 为 key ,结构为:{‘ 1_like ’: 100, ‘ 1_hate ’: 90, ‘ 2_like ’: 20, ‘ 2_hate ’: 10, ....},不建议 key 中包含长字符串,所以可以用 0 代表 like , 1 代表 hate ,于是成为:{‘ 1_0 ’: 100, ‘ 1_1 ’: 90, ‘ 1_0 ’: 20, ‘ 1_1 ’: 10, ....}
    第二种:直接用 catid_id_like 的形式,如: 1_1_like: 100 , 1_1_hate: 90 ,同样 0 代表 like , 1 代表 hate ,成为: 1_1_0: 100 , 1_1_1: 90

    上面适合不同的 catid 下有相同的 item_id ,如果不同的 catid 下面的 item_id 不存在重复的,那么就简单了,第二种,并且 key 中去掉 catid ,表示为: id_like ,如: 1_like: 100 , 1_hate: 90 ,同样 0 代表 like , 1 代表 hate ,成为: 1_0: 100 , 1_1: 90

    只是一种思路,具体细节根据 lz 情况自行调整。
    lianxiaoyi
        4
    lianxiaoyi  
       2016-06-13 09:47:24 +08:00
    @jsonfork 做好封装你就不会有这种感觉了。。。。。。
    jsonfork
        5
    jsonfork  
    OP
       2016-06-13 17:04:23 +08:00
    @tonghuashuai 不同的 catid 下会有相同的 item_id 。还有一种方案:使用 hmset , catid 同样为 key ,结构为:{`1`:`100_102`,`2`:`10_22`,...} ,`1` 为 item_id ,`100_102` , 100 为 like , 102 为 hate ,这种结构怎么样,有没有什么问题。
    tonghuashuai
        6
    tonghuashuai  
       2016-06-13 23:37:38 +08:00 via iPhone
    @jsonfork
    key value 的思想是唯一的 key 对应唯一的 value ,你这种方式叶能实现功能,但是 like 和 hate 操作都会更新同一个 key 的 value ,个人认为不太好,只是个人认为。
    jsonfork
        7
    jsonfork  
    OP
       2016-06-14 08:36:24 +08:00
    @tonghuashuai 嗯,用了第一种方式。 这样操作会方便些。 这个数据量如果大的话会有影响的吗。 就是意味着我们 10W 条数据,要产生 20W 的记录值。这样查询性能有影响吗。
    tonghuashuai
        8
    tonghuashuai  
       2016-06-14 08:47:34 +08:00
    @jsonfork
    hash 数据结构的时间复杂度是 O(1),所以 hget hset 的时间复杂度都是 O(1),所以数据量不会影响性能。
    jsonfork
        9
    jsonfork  
    OP
       2016-06-14 10:02:42 +08:00
    @tonghuashuai OK, 谢谢老司机指路!!
    caixu
        10
    caixu  
       2016-06-14 11:44:46 +08:00
    我建议是使用 zset, member 是 id, score 是 like << 32 + hate
    如果要 like zadd(id, 1<<32 + 1)
    如果是 hate zadd(id, 1)

    如果要批量获取 id 的 score 可以使用一个临时的 zset, 把 ids 放在这个 zset 总和原始数据进行 ZINTERSTORE:


    使用 hget 的问题不是 hget 本身效率的问题. 是太多 round trip.
    caixu
        11
    caixu  
       2016-06-14 14:08:21 +08:00
    @caixu
    纠正下:

    如果要 like ZINCRBY(id, 1<<32 + 1)
    如果是 hate ZINCRBY(id, 1)
    jsonfork
        12
    jsonfork  
    OP
       2016-06-14 16:26:39 +08:00
    @caixu 不太了解你说命令。看不怎么懂。 但是我发现你没有用到 catid ,因为我是用 catid 来做分类的, 每个 catid 下面会有相同的 item_id 。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1178 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 18:13 · PVG 02:13 · LAX 10:13 · JFK 13:13
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.