redis存储微博点赞的人,如何存储?
2015-11-02 18:57
666 查看
问题对人有帮助,内容完整,我也想知道答案
3
问题没有实际价值,缺少关键内容,没有改进余地
比如说有一个微博的TID是1。 UID为1,2,3,4,5,6,7,8,9的用户都给这个微博点赞了。用redis缓存框架存储的话如何存储。微博可能有几十万个。如果用
key->set(value) 这种形式的话 key是微博ID的标示 value是 [1,2,3,4,5,6,7,8,9]这种形式,这样的话有多少个微博就有多少个K-V存储。我想知道这样会有什么弊端吗?或者有什么更好的方法吗?
redis
链接
评论
更多
默认排序时间排序
答案对人有帮助,有参考价值
6
答案没帮助,是错误的答案,答非所问
滕亦飞 1.3k 1月15日
回答 · 1月15日 更新
可以采用多个HashSet存储。每一条微博只是HashSet内的一个子key。增加赞的数量可以采用HIncrBy命令。把TID分块,使得每个HashSet内的key不超过100个。官方文档表示HashSet在内部元素小于一百个的时候采用线性存储与扫描,跟同数据规模下树形结构相比效率更高,更省内存。
例如:TID为
如果要管理赞的用户,可以自定义数据格式。在用户数量少的时候把用户列表整个内嵌到HashSet的值域中。用户超过比如50人后将其单独整理出一个Set,在HashSet里保存Set的key。例:
由于绝大多数微博赞的用户均比较少,HashSet可以节省出不少全局空间的key(全局key比HashSet的key更耗内存)。
关于 @卖掉内裤去上网 的回答:
若采用in-place quicksort,50个用户的手动排序效率非常高,因为在这个数据规模下数据紧密存放带来的缓存友好性远胜于Redis ZSet相对于手动排序带来的提升。而赞的用户升上去后就会自动适应成set或者zset,保证算法时间复杂度。如果还担心效率,可以把排序好的UID列表重新写回HashSet的一个value中,以后没有数据改变的话直接使用。
究竟采用set还是zset还是要看楼主的需求。set加入一个成员的复杂度为O(1),zset是O(log N),但set就没有排序功能了。
链接
17 评论
更多
答案对人有帮助,有参考价值
4
答案没帮助,是错误的答案,答非所问
卖掉内裤去上网 877 1月15日
回答 · 1月15日 更新
不太推荐LS用HASH来存储点赞的数据. 因为没办法进行排序(如果需要的话. 我想一定需要)
目前 我们是这样处理的.
可以使用ZSET有序集合进行存储. 理论上说一个ZSET中, 10W以内的数量并无任何鸭梨. 也就是说一条微博点赞的人数再10W以内(这是不可能的).
恩再PS一下!!!
如果需要用到NOSQL这样的数据库来存储类似微博的数据的话, 可以这样存储:).
再再PS一下, 微博评论也是类似的存储方法. 只是需要约定$redis KEYS的名称. 比如:
c:<评论ID> 怎么和微博数据关联起来可以这样:
t:$tid:comments:scores (ZSET timestmap 评论ID);
这样取数据的时候就用PIPELINE方便很多了.
最后啰嗦一句, NOSQL这种数据库的 KEY 一定要设置好.
链接
9 评论
更多
答案对人有帮助,有参考价值
0
答案没帮助,是错误的答案,答非所问
yuankui 23 1月21日
回答 · 1月21日 更新
保存每个uid是否有必要,还是你觉得新浪微博就是这么搞的?大多数情况,其实大家只是关注一个数字,如果这样的话,那么用一个数字来存储就可以了{tid->count}
如果非要保存,建议还是用{tid->set(uid)}来保存
有个优化就是你可以设定一个阈值,比如超过100人点赞,就不再往里面加东西了,而仅仅加一个数字(当然这里需要你再存一个{tid->count})。因为超过1w的微博点赞,没人回去逐个把每个点赞的人都点开的。。
链接
2 评论
更多
3
问题没有实际价值,缺少关键内容,没有改进余地
比如说有一个微博的TID是1。 UID为1,2,3,4,5,6,7,8,9的用户都给这个微博点赞了。用redis缓存框架存储的话如何存储。微博可能有几十万个。如果用
key->set(value) 这种形式的话 key是微博ID的标示 value是 [1,2,3,4,5,6,7,8,9]这种形式,这样的话有多少个微博就有多少个K-V存储。我想知道这样会有什么弊端吗?或者有什么更好的方法吗?
redis
链接
评论
更多
默认排序时间排序
3 个回答
答案对人有帮助,有参考价值6
答案没帮助,是错误的答案,答非所问
滕亦飞 1.3k 1月15日
回答 · 1月15日 更新
可以采用多个HashSet存储。每一条微博只是HashSet内的一个子key。增加赞的数量可以采用HIncrBy命令。把TID分块,使得每个HashSet内的key不超过100个。官方文档表示HashSet在内部元素小于一百个的时候采用线性存储与扫描,跟同数据规模下树形结构相比效率更高,更省内存。
例如:TID为
123456的微博存在
z:1234的HashSet中,其key为56。假设最新的微博活跃程度也较高,那么绝大多数情况下被调用的HashSet只有区区几个,对CPU的缓存很友好。
如果要管理赞的用户,可以自定义数据格式。在用户数量少的时候把用户列表整个内嵌到HashSet的值域中。用户超过比如50人后将其单独整理出一个Set,在HashSet里保存Set的key。例:
# 内嵌UID的情况 hget z:1234 56 > "1,2,3,4"... # 使用set的情况 hget z:1234 56 > "UIDlist:10" smembers UIDlist:10 > 1) "1" > 2) "2" > ...
由于绝大多数微博赞的用户均比较少,HashSet可以节省出不少全局空间的key(全局key比HashSet的key更耗内存)。
关于 @卖掉内裤去上网 的回答:
若采用in-place quicksort,50个用户的手动排序效率非常高,因为在这个数据规模下数据紧密存放带来的缓存友好性远胜于Redis ZSet相对于手动排序带来的提升。而赞的用户升上去后就会自动适应成set或者zset,保证算法时间复杂度。如果还担心效率,可以把排序好的UID列表重新写回HashSet的一个value中,以后没有数据改变的话直接使用。
究竟采用set还是zset还是要看楼主的需求。set加入一个成员的复杂度为O(1),zset是O(log N),但set就没有排序功能了。
链接
17 评论
更多
答案对人有帮助,有参考价值
4
答案没帮助,是错误的答案,答非所问
卖掉内裤去上网 877 1月15日
回答 · 1月15日 更新
不太推荐LS用HASH来存储点赞的数据. 因为没办法进行排序(如果需要的话. 我想一定需要)
目前 我们是这样处理的.
可以使用ZSET有序集合进行存储. 理论上说一个ZSET中, 10W以内的数量并无任何鸭梨. 也就是说一条微博点赞的人数再10W以内(这是不可能的).
$redis->ZADD("t:$tid:liked", time(), $uid); //$tid 为你的微博ID, $uid 为你的点赞人的UID //取出点赞的人(支持按照点赞时间来排序的哦:)).. 按照LSD的说的 HASH取出来的值没有任何顺序的. $uids = $redis->ZREVRANGE("t:$tid:liked", $offset, $max, TRUE); //倒序取值 $uids = $redis->ZRANGE("t:$tid:liked", $offset, $max, TRUE); //顺序取值 //$offset 和 $max 这样来算 $pagesize = 20; $offset = ($page > 1) ? ($page - 1) * $pagesize : 0; $max = ($page * $pagesize) - 1; //一次性取出所有的这样取. $total = $redis->ZCARD("t:$tid:liked"); $uids = $redis->ZREVANGE("t:$tid:liked", 0, $total - 1, TRUE); //拿到的$uids 是一个array 哦.. //判断一个用户是否点赞了这一来哦 $redis->ZSCORE("t:$tid:liked", $uid); //取消赞这样来 $redis->ZREM("t:$tid:liked", $uid); //批量取消某短时间内的点赞这样操作 $redis->ZREMRANGEBYSCORE("t:$tid:liked", $start_timestamp, $end_timestamp); //诸如此类的操作, 要比HASH强很多.
恩再PS一下!!!
如果需要用到NOSQL这样的数据库来存储类似微博的数据的话, 可以这样存储:).
$pipe = $redis->MULTI(Redis::PIPELINE); $pipe->SET("t:$tid", json_encode($data)) //json这种格式存储貌似有点废物. 如果能想到更好的格式的话,不要用JSON, 因为JSON太大了.. 比如MSGPACK这个个是就比JSON要好很多 ->ZADD("t:scores", time(), $tid); $pipe->EXEC(); //PIPE 这样的操作赞爆了. 如果你的REDIS支持事务的话, PIPE就不是一个原子性的操作了 //取出数据的话就很好取出了!! $tid = $reids->ZREVRANGE("t:scores", 0, 100); $pipe = $redis->MULTI(Redis::PIPELINE); foreach($tid as $key=> $value){ $pipe->GET("t:$value"); } $list = $pipe->EXEC(); //$list就是你的数据啦
再再PS一下, 微博评论也是类似的存储方法. 只是需要约定$redis KEYS的名称. 比如:
c:<评论ID> 怎么和微博数据关联起来可以这样:
t:$tid:comments:scores (ZSET timestmap 评论ID);
这样取数据的时候就用PIPELINE方便很多了.
最后啰嗦一句, NOSQL这种数据库的 KEY 一定要设置好.
链接
9 评论
更多
答案对人有帮助,有参考价值
0
答案没帮助,是错误的答案,答非所问
yuankui 23 1月21日
回答 · 1月21日 更新
保存每个uid是否有必要,还是你觉得新浪微博就是这么搞的?大多数情况,其实大家只是关注一个数字,如果这样的话,那么用一个数字来存储就可以了{tid->count}
如果非要保存,建议还是用{tid->set(uid)}来保存
有个优化就是你可以设定一个阈值,比如超过100人点赞,就不再往里面加东西了,而仅仅加一个数字(当然这里需要你再存一个{tid->count})。因为超过1w的微博点赞,没人回去逐个把每个点赞的人都点开的。。
链接
2 评论
更多
相关文章推荐
- shell导出和导入redis
- Redis手册(String数据类型)
- Windows下Redis的安装和测试
- redis最佳实践
- Redis系列-存储篇hash主要操作函数小结
- 将Tomcat的Session数据存储在 Redis 库
- Redis能干啥?细看11种Web应用场景
- Kafka+Spark Streaming+Redis实时计算整合实践
- Kafka+Spark Streaming+Redis实时计算整合实践
- Kafka+Spark Streaming+Redis实时计算整合实践
- Kafka+Spark Streaming+Redis实时计算整合实践
- Redis 命令速查表
- 开发 Spring Redis 应用程序
- redis客户端Jedis源码分析系列——集合JedisByteHashMap
- redis 可视化监控工具
- redis邮件与事务
- redis
- Redis快速入门
- Redis服务器搭建/配置/及Jedis客户端的使用方法
- php Redis存储Session