redis存储微博点赞的人,如何存储?
怪我咯
怪我咯 2017-04-22 08:59:23
0
3
1116

比如说有一个微博的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存储。我想知道这样会有什么弊端吗?或者有什么更好的方法吗?

怪我咯
怪我咯

走同样的路,发现不同的人生

reply all(3)
刘奇

Multiple HashSet storage can be used. Each Weibo is just a subkey in the HashSet. You can use the HIncrBy command to increase the number of likes. Divide the TID into blocks so that the keys in each HashSet do not exceed 100. The official documentation states that HashSet uses linear storage and scanning when the internal elements are less than 100, which is more efficient and saves memory compared with the tree structure at the same data scale.

For example: In the HashSet with TID 123456的微博存在z:1234, its key is 56. Assuming that the latest Weibo is also highly active, in most cases only a few HashSets are called, which is very friendly to the CPU cache.

If you want to manage users who like it, you can customize the data format. When the number of users is small, embed the entire user list into the value field of HashSet. After there are more than 50 users, for example, separate them into a Set and save the key of the Set in the HashSet. Example:

bash# 内嵌UID的情况
hget z:1234 56
> "1,2,3,4"...

# 使用set的情况
hget z:1234 56
> "UIDlist:10"
smembers UIDlist:10
> 1) "1"
> 2) "2"
> ...

Since most Weibo users have fewer likes, HashSet can save a lot of global space keys (global keys consume more memory than HashSet keys).

Answer about @ sell your underwear and go online:
If in-place quicksort is used, the manual sorting efficiency of 50 users is very high, because at this data scale, the cache friendliness brought by compact storage of data is far better than the improvement brought by Redis ZSet compared to manual sorting. After the users who like it are promoted, they will automatically adapt to set or zset to ensure the time complexity of the algorithm. If you are still worried about efficiency, you can rewrite the sorted UID list back into a value of the HashSet, and use it directly if there is no data change in the future.

Whether to use set or zset still depends on the needs of the poster. The complexity of adding a member to set is O(1), and to zset is O(log N), but set has no sorting function.

大家讲道理

It is not recommended that LS use HASH to store like data. Because there is no way to sort (if necessary. I think it must be necessary)

Currently this is how we handle it.

You can use ZSET ordered sets for storage. Theoretically speaking, in a ZSET, there is no number within 100,000. In other words, the number of people who like a Weibo is within 100,000 (this is impossible).

php$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强很多. 

Well, please post it again!!!

If you need to use a database like NOSQL to store data like Weibo, you can store it like this:).

php$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 it again, Weibo comments are stored in a similar way. Just need to agree on the name of $redis KEYS. For example:
c:<Comment ID> How to associate it with Weibo data like this:

t:$tid:comments:scores (ZSET timestmap comment ID);

It is much more convenient to use PIPELINE when retrieving data.

Finally, the KEY of databases like NOSQL must be set up.

刘奇
  1. Is it necessary to save each uid, or do you think this is what Sina Weibo does? In most cases, everyone only pays attention to a number. If this is the case, then just use a number to store {tid->count}

  2. If you have to save, it is recommended to use {tid->set(uid)} to save

  3. An optimization is that you can set a threshold. For example, if more than 100 people like it, you will no longer add anything to it, but only add a number (of course you need to save another {tid->count}) . Because there are more than 10,000 likes on Weibo, no one goes back to click on everyone who likes it one by one. .

Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template