PHP缓存 - Redis的安装和使用

1. 在宝塔环境下可直接进行安装
2. 安装完成后需要进入指定的php环境下进行安装redis扩展
3. 在thinkphp下进行自定义封装Redis类

<?php

namespace app\lib\cache;


use think\Config;

class Redis
{
    private static $read_instance = null;
    private static $write_instance = null;

    public static function write()
    {
        $option = [
            'host' => Config::get('cache.redis_w_host') ?? '127.0.0.1',
            'port' => Config::get('cache.redis_w_port') ?? 6379,
        ];
        if (is_null(self::$write_instance)) {
            self::$write_instance = new \Redis();
            self::$write_instance->connect($option['host'], $option['port']);
        }
        return self::$write_instance;
    }

    public static function read()
    {
        $option = [
            'host' => Config::get('cache.redis_r_host') ?? '127.0.0.1',
            'port' => Config::get('cache.redis_r_port') ?? 6379,
        ];
        if (is_null(self::$read_instance)) {
            self::$read_instance = new \Redis();
            self::$read_instance->connect($option['host'], $option['port']);
        }
        return self::$read_instance;
    }

    //字符串类型------------------------------------------
    /**
     * 赋值 默认永久有效
     * @param $key
     * @param $value
     * @param int $expire
     * @return bool
     */
    public static function set($key, $value, $expire = 0)
    {
        if ($expire == 0) {
            return self::write()->set($key, $value);
        } else {
            return self::write()->setex($key, $expire, $value);
        }
    }

    /**
     * 查询缓存值,单个或数组
     * @param $key 键
     * @return mixed
     */
    public static function get($key)
    {
        $func = is_array($key) ? 'getMulti' : 'get';
        return self::read()->{$func}($key);
    }

    /**
     * 自增
     * @param $key
     * @param int $number
     * @return int
     */
    public static function incr($key, $number = 1)
    {
        if ($number == 1) {
            return self::write()->incr($key);
        } else {
            return self::write()->incrBy($key, $number);
        }
    }

    /**
     * 自减
     * @param $key
     * @param int $number
     * @return int
     */
    public static function decr($key, $number = 1)
    {
        if ($number == 1) {
            return self::write()->decr($key);
        } else {
            return self::write()->decrBy($key, $number);
        }
    }

    /**
     * 获取字符串长度
     * @param $key
     * @return int
     */
    public static function strlen($key)
    {
        return self::read()->strlen($key);
    }

    // Hash类型------------------------------------------

    /**
     * 赋单个值
     * @param $key
     * @param $field
     * @param $value
     * @return int
     */
    public static function hSet($key, $field, $value)
    {
        return self::write()->hSet($key, $field, $value);
    }

    /**
     * 取指定字段值,或取所有字段名和字段的值
     * @param $key
     * @param string $field
     * @return array|string
     */
    public static function hGet($key, $field = '')
    {
        if (empty($field)) {
            return self::read()->hGetAll($key);
        } else {
            return self::read()->hGet($key, $field);
        }
    }

    /**
     * 赋多个值
     * @param $key
     * @param $data ['field1'=>'value1','field2'=>'value2']
     * @return bool
     */
    public static function hMset($key, $data)
    {
        return self::write()->hMset($key, $data);
    }

    /**
     * 取多个值
     * @param $key
     * @param $dataField ['field1','field2']
     * @return array
     */
    public static function hMGet($key, $dataField)
    {
        return self::read()->hMGet($key, $dataField);
    }


    /**
     * 获取字段的数量
     * @param $key
     * @return int
     */
    public static function hLen($key)
    {
        return self::read()->hLen($key);
    }

    /**
     * 自增
     * @param $key
     * @param $field
     * @param int $number
     * @return int
     */
    public static function hIncrBy($key, $field, $number = 1)
    {
        return self::write()->hIncrBy($key, $field, $number);
    }


    // List类型------------------------------------------

    /**
     * 向列表左端添加元素
     * @param $key
     * @param $value
     * @return int
     */
    public static function lPush($key, $value)
    {
        return self::write()->lPush($key, $value);
    }

    /**
     * 向列表右端弹出元素
     * @param $key
     * @return string
     */
    public static function rPop($key)
    {
        return self::read()->rPop($key);
    }

    /**
     * 返回列表的长度
     * @param $key
     * @return int
     */
    public static function lLen($key)
    {
        return self::read()->lLen($key);
    }
}

4.调用示例,简单商品秒杀

<?php

namespace app\api\controller\v1;


use app\lib\cache\Memcached;
use app\lib\cache\Redis;

class Test extends BaseController
{
    public function t1($uid,$gid)
    {

//        return 'a';
//        Memcached::set('t1','test2');
//        echo Memcached::delete('t1');
//        echo Memcached::get('t1');

//        return Redis::hSet('test_1','name','刘先生');
        //$r = Redis::hGet('test_1');

        // 商品秒杀简单示例

        // 准备1,商品秒杀状态 0正常秒杀中,1秒杀结束,这里需要与数据库秒杀商品字段同步
        // 准备2,秒杀队列(用户ID),参与该次秒杀的人
        // 准备3,秒杀n个,设置几个可以秒杀成功
//        $uid = input('get.uid');
//        $gid = input('get.gid');
        $limit_number = 2;// 设置此商品只能2个人可以秒杀

        $redis_ms_status = 'ms_status' . $gid;
        $redis_ms_users = 'ms_users' . $gid;

        // 判断当前的商品是否已结束
        if (Redis::get($redis_ms_status) != 0) {
            return [
                'code' => '90002',
                'msg' => '秒杀已经结束'
            ];
        }

        // 获取当前队列个数
        $number = Redis::lLen($redis_ms_users);
        if ($number >= $limit_number) { // 判断是否已秒杀完
            Redis::set($redis_ms_status, 1);// 设置商品秒杀状态
            return [
                'code' => '90001',
                'msg' => '秒杀失败'
            ];
        }

        // ... 判断其他情况,如该用户是否已成功参与了秒杀

        // 秒杀成功
        Redis::lPush($redis_ms_users, $uid);
        return [
            'code' => '90000',
            'msg' => '秒杀成功'
        ];

    }

    // 后台查看秒杀结果流程
    // 1.查看秒杀等同于把秒杀结果进行入库
    // 注意1,查看前把商品秒杀状态设置为1,防止从右弹出一个单元时,左边又可以进行秒杀
    // 注意2,弹出单元时,把秒杀信息进行入库,如果期中出现问题,需要把该单元重新压回,防止队列单元丢失
    public function getMs($gid)
    {
//        $gid = input('get.gid');// 查看哪个秒杀商品
        $redis_ms_status = 'ms_status' . $gid;
        $redis_ms_users = 'ms_users' . $gid;
        Redis::set($redis_ms_status, 1);//该商品秒杀状态设置1 秒杀已结束
        for ($i = 0; $i <= Redis::lLen($redis_ms_users); $i++) {
            $user_id = Redis::rPop($redis_ms_users);
            //....... 其他业务逻辑处理,入库操作,异常处理,
            echo '用户'.$user_id.'参与'.$gid.'号商品秒杀成功';
        }
    }

}
Last modification:June 9th, 2019 at 03:12 pm
如果觉得我的文章对你有用,请随意赞赏

Leave a Comment