Redis实现缓存点赞思路

纵所周知,优酷和抖音这类直播平台都会有点击屏幕就点赞的功能,这类不太重要的数据,交给redis处理是最优的,定时存入MySQL数据库中,就可以实现数据的持久化。
本博基于tp6框架技术,结合think-queue消息队列,middleware中间件。
实现redis向mysql点赞的同步。

本博使用消息队列:composer require topthink/think-queue

一、controller层

主要是将前端的数据存到redis之中,用redis的哈希表储存;
redis的哈希表存储键值对:cache()->hset(‘v5_like_num’, ‘user_1’,0);
redis的哈希表获取键值对:cache()->hget(‘v5_like_num’, ‘user_1’);
redis的哈希表步进value值:cache()->hincrby(‘v5_like_num’, ‘user_1’, ‘步进的整数’);

namespace app\v5\controller;

use app\BaseController;
use think\facade\Db;

/**
 * redis点赞
 */
class Redis extends BaseController
{
    /**
     * 显示视图:这里的视图只是为了方便展示
     */
    public function index()
    {
        $data['res'] = Db::table('v5_like_num')->select()->toArray();
        $data['redis_like_num'] = cache()->hget('v5_like_num', 'user_1');
        // halt($data);
        return view('redis/index', $data);
    }

    /**
     * 添加数据到redis接口
     */
    public function add()
    {
        $step = (int)request()->post('step', 0);
        //添加redis
        cache()->hincrby('v5_like_num', 'user_1', $step);
        // dump($step);
        // dump(cache()->hget('v5_like_num', 'user_1'));
    }
}

视图层参考:view/redis/index
源码:https://github.com/xiaopacairq/tpAdmin/blob/main/app/v5/view/redis/index.php
核心代码如下:

// 点赞攒值,每3秒缓存到redis一次
setInterval(function() {
            $.post('/v5/redis/add', {
                step,
            }, function(res) {
                step = 0;
            }, '')
        }, 3000)

二、数据库层

  1. Mysql数据库
  2. Reids数据库

三、Job工作类

  1. queue的配置选项config/queue.php,默认是sync同步执行,可修改为redis缓存
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------

return [
    'default'     => 'redis',
    'connections' => [
        'sync'     => [
            'type' => 'sync',
        ],
        'database' => [
            'type'       => 'database',
            'queue'      => 'default',
            'table'      => 'jobs',
            'connection' => null,
        ],
        'redis'    => [
            'type'       => 'redis',
            'queue'      => 'default',
            'host'       => '127.0.0.1',
            'port'       => 6379,
            'password'   => '',
            'select'     => 0,
            'timeout'    => 0,
            'persistent' => false,
        ],
    ],
    'failed'      => [
        'type'  => 'none',
        'table' => 'failed_jobs',
    ],
];

编写Job工作类,可参考文档:https://packagist.org/packages/topthink/think-queue
具体工作内容:将redis缓存的数据定时5秒存入到mysql中

<?php

namespace app\job;

use think\queue\Job;
use think\facade\Db;

class Job1
{

    public function fire(Job $job, $data)
    {
        $isJob = $this->redisToMysql($data);
        if ($isJob) {
            $job->delete();
        } else {
            //通过这个方法可以检查这个任务已经重试了几次了
            $attempts = $job->attempts();
            if ($attempts == 0 || $attempts == 1) {
                // 重新发布这个任务
                $job->release(5); //$delay为延迟时间,延迟5S后继续执行
            } elseif ($attempts == 2) {
                $job->release(5); // 延迟5S后继续执行
            }
        }
    }

    public function failed($data)
    {

        // ...任务达到最大重试次数后,失败了
    }

    private function redisToMysql($number)
    {
		//将redis数据存入到mysql数据库当中
        $isAdd = Db::table('v5_like_num')
            ->where('title', '文章1')
            ->inc('like_num', $number)
            ->update();
        if ($isAdd) {
            return true;
        } else {
            return false;
        }
    }
}

四、middleware中间件

中间件工作:定时执行队列 Queue::later(5, 'Job1@fire', $number, 'jobdemo'); 队列工作时,需要在命令行执行:php think queue:work --queue jobdemo

  1. 注册中间件
<?php
// 全局中间件定义文件
return [
    // 全局请求缓存
    // \think\middleware\CheckRequestCache::class,
    // 多语言加载
    // \think\middleware\LoadLangPack::class,
    // Session初始化
    \think\middleware\SessionInit::class,
	// 初始化消息中间件
    app\v5\middleware\RedisToMysql::class,
];
  1. 实现中间件
<?php

namespace app\v5\middleware;

use think\facade\Queue;

class RedisToMysql
{
    public function handle($request, \Closure $next)
    {
        $number = (int)cache()->hget('v5_like_num', 'user_1');
        //执行队列
        $isPushed = Queue::later(5, 'Job1@fire', $number, 'jobdemo');
        if ($isPushed) {
            cache()->hset('v5_like_num', 'user_1', 0); //队列执行成功,让点赞步进值为0
        }
        return $next($request);
    }
}
执行php think queue:work --queue jobdemo,只有出现processed状态,才算队列执行成功,一直是processing状态,大概率是Job工作类写错了!

redis怎么缓存tcp连接 redis缓存实现思路_php


实现结果是:

  • 前端点赞,3秒后传入到后端接口
  • 后端接口将前端的点赞集合缓存到redis
  • 中间件每隔5秒自动将redis的数据缓存到mysql,并清空redis缓存

redis怎么缓存tcp连接 redis缓存实现思路_缓存_02

本博到此结束,thinkphp,以及勤劳的自己!