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

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

怪我咯
怪我咯

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

membalas semua(3)
刘奇

Boleh menggunakan berbilang storan HashSet. Setiap Weibo hanyalah subkunci dalam HashSet. Anda boleh menggunakan arahan HIncrBy untuk meningkatkan bilangan suka. Bahagikan TID kepada blok supaya kunci dalam setiap HashSet tidak melebihi 100. Dokumentasi rasmi menyatakan bahawa HashSet menggunakan storan dan pengimbasan linear apabila elemen dalaman kurang daripada 100, yang lebih cekap dan menjimatkan memori berbanding dengan struktur pokok pada skala data yang sama.

Contohnya: Weibo dengan TID 123456 wujud dalam HashSet z:1234, dan kuncinya ialah 56. Dengan mengandaikan bahawa Weibo terkini juga sangat aktif, dalam kebanyakan kes hanya beberapa HashSet dipanggil, yang sangat mesra kepada cache CPU.

Jika anda ingin mengurus pengguna yang menyukainya, anda boleh menyesuaikan format data. Apabila bilangan pengguna kecil, benamkan keseluruhan senarai pengguna ke dalam medan nilai HashSet. Selepas terdapat lebih daripada 50 pengguna, contohnya, pisahkan mereka ke dalam Set dan simpan kekunci Set dalam HashSet. Contoh:

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

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

Memandangkan kebanyakan pengguna Weibo mempunyai kurang suka, HashSet boleh menyimpan banyak kekunci ruang global (kunci global menggunakan lebih banyak memori daripada kunci HashSet).

Jawapan tentang @menjual seluar dalam dan pergi ke dalam talian:
Jika quicksort di tempat digunakan, kecekapan pengisihan manual bagi 50 pengguna adalah sangat tinggi, kerana pada skala data ini, keramahan cache yang dibawa oleh penyimpanan data padat adalah jauh lebih baik daripada peningkatan yang dibawa oleh Redis ZSet berbanding dengan pengisihan manual. Selepas pengguna yang menyukainya dipromosikan, mereka secara automatik akan menyesuaikan diri dengan set atau zset untuk memastikan kerumitan masa algoritma. Jika anda masih bimbang tentang kecekapan, anda boleh menulis semula senarai UID yang diisih kembali ke dalam nilai dalam HashSet dan menggunakannya secara langsung jika tiada perubahan data pada masa hadapan.

Sama ada nak guna set atau zset masih bergantung pada keperluan poster. Kerumitan menambah ahli kepada set ialah O(1), dan kepada zset ialah O(log N), tetapi set tidak mempunyai fungsi pengisihan.

大家讲道理

Tidak digalakkan LS menggunakan HASH untuk menyimpan seperti data Kerana tiada cara untuk mengisih (jika perlu. Saya rasa ia mesti perlu)

Buat masa ini beginilah cara kami mengendalikannya.

Anda boleh menggunakan set pesanan ZSET untuk storan Secara teorinya, dalam ZSET, tidak ada nombor dalam 100,000 dalam erti kata lain, bilangan orang yang menyukai Weibo adalah dalam 100,000 (ini adalah mustahil).

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强很多. 
Hmm, PS lagi!!!

Jika anda perlu menggunakan pangkalan data seperti NOSQL untuk menyimpan data seperti Weibo, anda boleh menyimpannya seperti ini:).

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 sekali lagi, komen Weibo disimpan dengan cara yang sama Anda hanya perlu bersetuju dengan nama $redis KEYS Sebagai contoh:

c:<ID Komen> Cara mengaitkannya dengan data Weibo seperti ini:

t:$tid:comments:scores (ID ulasan peta masa ZSET);

Adalah lebih mudah untuk menggunakan PIPELINE apabila mendapatkan data.

Akhir sekali, KUNCI pangkalan data seperti NOSQL mesti disediakan dengan betul.

刘奇
  1. Adakah perlu untuk menyimpan setiap uid, atau adakah anda fikir ini adalah yang Sina Weibo lakukan? Dalam kebanyakan kes, semua orang hanya memberi perhatian kepada nombor Jika ini berlaku, maka hanya gunakan nombor untuk menyimpan {tid->count}

  2. Jika anda perlu menyimpan, adalah disyorkan untuk menggunakan {tid->set(uid)} untuk menyimpan

  3. Pengoptimuman ialah anda boleh menetapkan ambang Contohnya, jika lebih daripada 100 orang menyukainya, anda tidak akan menambah apa-apa lagi padanya, tetapi hanya menambah nombor (sudah tentu anda perlu menyimpan { yang lain. tid-&gt ;count}). Kerana terdapat lebih daripada 10,000 suka di Weibo, tiada siapa yang kembali untuk mengklik pada semua orang yang menyukainya satu demi satu. .

Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan