您好,登錄后才能下訂單哦!
這篇文章主要介紹“PHP+Redis怎么實現點贊效果”,在日常操作中,相信很多人在PHP+Redis怎么實現點贊效果問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”PHP+Redis怎么實現點贊效果”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
點贊其實是一個很有意思的功能。基本的設計思路有大致兩種, 一種自然是用mysql(寫了幾百行的代碼都還沒寫完,有毒)啦
數據庫直接落地存儲, 另外一種就是利用點贊的業務特征來扔到redis(或memcache)中, 然后離線刷回mysql等。
我這里所講的功能都是基于我之前的項目去說的,所以有些地方可以不用管的,我主要是記錄這個功能的實現思路,當你理解了,基本想用什么鬼語言寫都一樣的。
直接寫入Mysql是最簡單的做法。
做三個表即可,
comment_info
記錄文章的主要內容,主要有like_count,hate_count,score這三個字段是我們本次功能的主要字段。
comment_like
記錄文章被贊的次數,已有多少人贊過這種數據就可以直接從表中查到;
user_like_comment
記錄用戶贊過了哪些文章, 當打開文章列表時,顯示的有沒有贊過的數據就在這里面;
數據庫讀寫壓力大
熱門文章會有很多用戶點贊,甚至是短時間內被大量點贊, 直接操作數據庫從長久來看不是很理想的做法
redis主要的特點就是快, 畢竟主要數據都在內存嘛;
另外為啥我選擇redis而不是memcache的主要原因在于redis支持更多的數據類型, 例如hash, set, zset等。
下面具體的會用到這幾個類型。
性能高
緩解數據庫讀寫壓力
其實我更多的在于緩解寫壓力, 真的讀壓力, 通過mysql主從甚至通過加入redis對熱點數據做緩存都可以解決,
寫壓力對于前面的方案確實是不大好使。
開發復雜
這個比直接寫mysql的方案要復雜很多, 需要考慮的地方也很多;
不能保證數據安全性
redis掛掉的時候會丟失數據, 同時不及時同步redis中的數據, 可能會在redis內存置換的時候被淘汰掉;
不過對于我們點贊而已, 稍微丟失一點數據問題不大;
其實上面第二點缺點是可以避免的,這就涉及到redis 的一些設計模式,不懂沒關系,我盡量詳細的寫,后面我會給出如何解決這個缺點。
設計功能前知識準備
1.將要用到的redis數據類型(具體的類型說明,請看底部鏈接,有詳細說明):
zset 這個類型主要用來做排序或者數字的增減,這里被用作like 和hate的數字記錄,以及熱度的記錄。
set 這個是無序集合,主要用來記錄今天需不需要更新,將今天被點贊(包括點討厭)過的文章id記錄下來,方便晚上或者有時間對這部分數據更新。
hash 這個是散列,主要用來存儲數據以及索引。這里被用來記錄用戶對哪個文章點了什么,方便下次判斷(我看過一些網上的介紹使用set來記錄,那個也可以,但是本人覺得這樣做更省空間,以及方便管理,再有就是hash的速度快)。
list 這個是隊列大佬,我們的數據能不能 安全 回到mysql就靠它了。
2.關于熱度如何去判斷:
大家都知道,文章獲得點贊數越高,文章的熱度就越高,那么怎么判斷呢?不就直接記錄點贊數就行啦,但是對于最新的文章怎么辦?例如有一篇文章一年前發布的,獲得50個贊,有篇最新文章獲得49個贊,但是按照上面所說的一年前的文章熱度還比最新的高,這就不合理了,文章都是時效性,誰都想看最新最熱的。
so!我們要換個方法去處理這個時效性,絕大部分語言都有 時間戳 生成的方法,時間戳隨著時間越新,數字越大,直接將時間戳初始化賦值給文章的score,這樣最新的文章相比以前的文章就會靠前了。接著是點贊對score的影響,我們假設一天得到20個贊算是一天最熱,一天60*60*24=86400秒,然后得到一個贊就是得到86400 / 20 = 4320分。具體數字看自己的業務需求定,我只是舉例子而已。點hate當然也會減去相應的數字。
<?php
class Good
{
public $redis = null;
//60*60*24/20=4320,每個點贊得到的分數,反之即之。
public $score = 4320;
//點贊增加數,或者點hate增加數
public $num = 1;
//init redis
public $redis_host = "127.0.0.1";
public $redis_port = "6379";
public $redis_pass = "";
public function __construct()
{
$this->redis = new Redis();
$this->redis->connect($this->redis_host,$this->redis_port);
$this->reids->auth($this->redis_pass);
}
/**
* @param int $user_id 用戶id
* @param int $type 點擊的類型 1.點like,2.點hate
* @param int $comment_id 文章id
* @return string json;
*/
public function click($user_id,$type,$comment_id)
{
//判斷redis是否已經緩存了該文章數據
//使用:分隔符對redis管理是友好的
//這里使用redis zset-> zscore()方法
if($this->redis->zscore("comment:like",$comment_id))
{
//已經存在
//判斷點的是什么
if($type==1)
{
//判斷以前是否點過,點的是什么?
//redis hash-> hget()
$rel = $this->redis->hget("comment:record",$user_id.":".$comment_id);
if(!$rel)
{
//什么都沒點過
//點贊加1
$this->redis->zincrby("comment:like",$this->num,$comment_id);
//增加分數
$this->redis->zincrby("comment:score",$this->score,$comment_id);
//記錄上次操作
$this->redis->hset("comment:record",$user_id.":".$comment_id,$type);
$data = array(
"state" => 1,
"status" => 200,
"msg" => "like+1",
);
}
else if($rel==$type)
{
//點過贊了
//點贊減1
$this->redis->zincrby("comment:like",-($this->num),$comment_id);
//增加分數
$this->redis->zincrby("comment:score",-($this->score),$comment_id);
$data = array(
"state" => 2,
"status" => 200,
"msg" => "like-1",
);
}
else if($rel==2)
{
//點過hate
//hate減1
$this->redis->zincrby("comment:hate",-($this->num),$comment_id);
//增加分數
$this->redis->zincrby("comment:score",$this->score+$this->score,$comment_id);
//點贊加1
$this->redis->zincrby("comment:like",$this->num,$comment_id);
//記錄上次操作
$this->redis->hset("comment:record",$user_id.":".$comment_id,$type);
$data = array(
"state" => 3,
"status" => 200,
"msg" => "like+1",
);
}
}
else if($type==2)
{
//點hate和點贊的邏輯是一樣的。參看上面的點贊
$rel = $this->redis->hget("comment:record",$user_id.":".$comment_id);
if(!$rel)
{
//什么都沒點過
//點hate加1
$this->redis->zincrby("comment:hate",$this->num,$comment_id);
//減分數
$this->redis->zincrby("comment:score",-($this->score),$comment_id);
//記錄上次操作
$this->redis->hset("comment:record",$user_id.":".$comment_id,$type);
$data = array(
"state" => 4,
"status" => 200,
"msg" => "hate+1",
);
}
else if($rel==$type)
{
//點過hate了
//點hate減1
$this->redis->zincrby("comment:hate",-($this->num),$comment_id);
//增加分數
$this->redis->zincrby("comment:score",$this->score,$comment_id);
$data = array(
"state" => 5,
"status" => 200,
"msg" => "hate-1",
);
return $data;
}
else if($rel==2)
{
//點過like
//like減1
$this->redis->zincrby("comment:like",-($this->num),$comment_id);
//增加分數
$this->redis->zincrby("comment:score",-($this->score+$this->score),$comment_id);
//點hate加1
$this->redis->zincrby("comment:hate",$this->num,$comment_id);
$data = array(
"state" => 6,
"status" => 200,
"msg" => "hate+1",
);
return $data;
}
}
}
else
{
//未存在
if($type==1)
{
//點贊加一
$this->redis->zincrby("comment:like",$this->num,$comment_id);
//分數增加
$this->redis->zincrby("comment:score",$this->score,$comment_id);
$data = array(
"state" => 7,
"status" => 200,
"msg" => "like+1",
);
}
else if($type==2)
{
//點hate加一
$this->redis->zincrby("comment:hate",$this->num,$comment_id);
//分數減少
$this->redis->zincrby("comment:score",-($this->score),$comment_id);
$data = array(
"state" => 8,
"status" => 200,
"msg" => "hate+1",
);
}
//記錄
$this->redis->hset("comment:record",$user_id.":".$comment_id,$type);
}
//判斷是否需要更新數據
$this->ifUploadList($comment_id);
return $data;
}
public function ifUploadList($comment_id)
{
date_default_timezone_set("Asia/Shanghai");
$time = strtotime(date('Y-m-d H:i:s'));
if(!$this->redis->sismember("comment:uploadset",$comment_id))
{
//文章不存在集合里,需要更新
$this->redis->sadd("comment:uploadset",$comment_id);
//更新到隊列
$data = array(
"id" => $comment_id,
"time" => $time,
);
$json = json_encode($data);
$this->redis->lpush("comment:uploadlist",$json);
}
}
}
//調用
$user_id = 100;
$type = 1;
$comment_id= 99;
$good = new Good();
$rel = $good->click($user_id,$type,$comment_id);
var_dump($rel);
到此,關于“PHP+Redis怎么實現點贊效果”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。