<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                # PHP+Redis 實例【一】點贊 + 熱度 這次的開篇,算是總結下這段時間來的積累吧,廢話不多說,直接干! **前言** 點贊其實是一個很有意思的功能。基本的設計思路有大致兩種, 一種自然是用mysql(寫了幾百行的代碼都還沒寫完,有毒)啦 數據庫直接落地存儲, 另外一種就是利用點贊的業務特征來扔到redis(或memcache)中, 然后離線刷回mysql等。 我這里所講的功能都是基于我之前的項目去說的,所以有些地方可以不用管的,我主要是記錄這個功能的實現思路,當你理解了,基本想用什么鬼語言寫都一樣的。 ### 直接寫入Mysql 直接寫入Mysql是最簡單的做法。 做三個表即可, comment_info 記錄文章的主要內容,主要有like_count,hate_count,score這三個字段是我們本次功能的主要字段。 comment_like 記錄文章被贊的次數,已有多少人贊過這種數據就可以直接從表中查到; user_like_comment 記錄用戶贊過了哪些文章, 當打開文章列表時,顯示的有沒有贊過的數據就在這里面; **缺點** 數據庫讀寫壓力大 熱門文章會有很多用戶點贊,甚至是短時間內被大量點贊, 直接操作數據庫從長久來看不是很理想的做法 ## redis存儲隨后批量刷回數據庫 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); ~~~ 溫馨提示:   1.上面代碼只是一個實現的方法之一,里面的代碼沒精分過,適合大部分小伙伴閱讀。用心看總有收獲。   2.對于第三方接口,應該在外面包裝多一層的,但是邊幅有限,我就不做這么詳細,提示,大家可以作為參考。   3.剩下的將數據返回數據的方法,等下篇再繼續了。歡迎大家來交流心得。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看