Redis实战之商品相关缓存(php代码实现)

电商商品缓存

主要解决问题

  1. 登录cookie数量过多的更新问题
  2. 购物车cookie
  3. 缓存生成的网页
  4. 缓存商品信息
  5. 分析网页访问记录

具体代码

<?php
/**
 * Created by PhpStorm.
 * User: daneil
 * Date: 21-8-24
 * Time: 下午11:21
 */
class Token
{
    private $redis = null;
    private $login_key = 'login:';
    private $recent_key = 'recent:';
    private $view_key = 'view:';
    private $cart_key = 'cart:';

	// 测试方法,可忽略
    public function test() {
        $this->redis->zAdd('test_score',1,'a');
    }

    public function __construct()
    {
        $this->redis = new \Redis();
        $this->redis->connect('172.17.0.3','6379','5');
        $this->redis->select(7);
    }

    // 检查token返回user_id
    public function checkToken($token) {
        $user_id = $this->redis->hGet($this->login_key, $token);
        if (empty($user_id)) {
            echo 'token验证失败!';
            exit();
        }
        return $user_id;
    }

    // 更新token
    public function updateToken($token, $user_id, $item_id='') {
        $time = time();
        // 更新hash中的token
        $this->redis->hSet($this->login_key,$token,$user_id);
        // 加入到最近登录
        $this->redis->zAdd($this->recent_key,$time,$token);
        //商品ID不为空
        if ($item_id) {
            // 加入到浏览记录中
            $this->redis->zAdd($this->view_key.$token, $time, $item_id);
            // 只保留最新的2条
            $this->redis->zRemRangeByRank($this->view_key.$token, 0, -3);
            // 将浏览过的数据商品 view:item_id 分值 -1
            $this->redis->zIncrBy($this->view_key, $item_id, -1);
        }
        echo 'token 更新成功!';
        exit();
    }

    // 清除session
    public function cleanSessions() {
        $flag = false;
        $limit = 1000000;
        while (!$flag) {
            // 计算recent:的数量
            $count = $this->redis->zCard($this->recent_key);
            if ($count <= $limit) {
                sleep(1);
                continue;
            } else {
                //$flag = true;
                $end_index = min($count-$limit,100);
                $tokens = $this->redis->zRange(0,$end_index-1);
                foreach ($tokens as $token) {
                    //$session_key[] = 'viewed:'.$token; //给被删除的令牌构建键名
                    $this->redis->delete($this->view_key.$token);
                    // 增加一个删除用户的购物车
                    $this->redis->delete($this->cart_key.$token);
                    // 删除token
                    $this->redis->del($this->login_key.$token);
                    // 从最近登录中移除
                    $this->redis->zRem($this->recent_key, $token);
                }
            }
        }
    }

    // 加入购物车
    public function addCart($token, $item_id, $count) {
        // 商品真实性
        if ($count <= 0) {
            // 从购物车清除
            $this->redis->hDel($this->cart_key.$token, $item_id);
        } else {
            // 加入购物车,书上说的是覆盖,我个人觉得自增应该是比较合理,除非是输入的指定数量
            $this->redis->hSet($this->cart_key.$token, $item_id, $count);
        }
        return true;
    }

	// 移除非热门商品缓存
    public function rescalViewed() {
        $quit = false;
        while (!$quit) {
            // 删除排名在20000名之后的商品缓存
            $this->redis->zRemRangeByRank($this->view_key,0, -20001);
            // 将浏览次数降低为原来的一半(这里不懂为何要降低一半)
            $this->redis->zInterstore($this->view_key,[$this->view_key],[0.5],'SUM');
        }
    }



}

// zset特性分值越高,排名越后

$token = new Token();
//$token->updateToken('abc1',1,'good_1');
//$token->updateToken('abc1',1,'good_5');
$token->test();
posted @ 2021-09-05 16:10  Dan_eil  阅读(207)  评论(0编辑  收藏  举报