前言

今日给 PHPHub 开发了记录用户「最后活跃时间」的小功能,现在趁着热乎将相关实现逻辑写出来,欢迎大家指出不足。

基本思路

通过 Middleware 捕获用户的所有请求;

记录用户的请求时间,将数据放入缓存 (Redis) 中;

通过 Cron 每十分钟将缓存 (Redis) 里的数据同步到数据库中;

读取数据:先从 Redis 中读取数据,如 Redis 中没有,则从数据库中获取数据并同步到 Redis 中。

下文中我将针对每一个步骤进行详细说明。

捕获用户的所有请求

只有捕获用户的所有请求,我们才能实时的记录用户的最后活跃时间。在这里我们通过 中间件 来实现此逻辑。以下是生成中间件的具体操作:

1). 运行以下命令,生成 RecordLastActivedTime 中间件。

php artisan make:middleware RecordLastActivedTime

2). 在 app/Http/Kernel.php 中添加以下配置,将 RecordLastActivedTime 设置为全局中间件。

protected $middleware = [

...

\App\Http\Middleware\RecordLastActivedTime::class,

];

3). 在 app\Http\Middleware\RecordLastActivedTime.php 文件中添加逻辑代码

...

use Closure;

use Auth;

class RecordLastActivedTime

{

public function handle($request, Closure $next)

{

if (Auth::check()) {

// 在这里记录用户的访问时间,下文将介绍此方法。

Auth::user()->recordLastActivedAt();

}

return $next($request);

}

}

这样登录用户在访问我们网站任何一个页面时,都会进入到 RecordLastActivedTime 中,接下来我们将处理「记录用户请求时间」的逻辑。

记录用户的请求时间,将数据放入 Redis 中

现在,我们需要将用户的「最后活跃时间」存放到 Redis 中,并且接下来的读写操作都在 Redis 里进行,以减少数据库的开销。下面是具体操作:

1). 在 app/Models/User.php 中添加以下方法:

public function recordLastActivedAt()

{

$now = Carbon::now()->toDateTimeString();

// 这个 Redis 用于数据库更新,数据库每同步一次则清空一次该 Redis 。

$update_key = 'actived_time_for_update';

$update_data = Cache::get($update_key);

$update_data[$this->id] = $now;

Cache::forever($update_key, $update_data);

// 这个 Redis 用于读取,每次要获取活跃时间时,先到该 Redis 中获取数据。

$show_key = 'actived_time_data';

$show_data = Cache::get($show_key);

$show_data[$this->id] = $now;

Cache::forever($show_key, $show_data);

}

actived_time_for_update 和 actived_time_data 的数据结构如下:

array:4 [

1 => "2016-07-31 16:05:44"

2 => "2016-07-31 16:04:48"

3 => "2016-07-30 22:06:48"

4 => "2016-07-29 08:04:11"

]

2). 在 RecordLastActivedTime 中间件中调用 recordLastActivedAt

class RecordLastActivedTime

{

public function handle($request, Closure $next)

{

if (Auth::check()) {

Auth::user()->recordLastActivedAt();

}

return $next($request);

}

}

至此,只要登录的用户每访问一次网站,都会将其「最后活跃时间」记录到 Redis 中。

定期将 Redis 里的数据同步到数据库中

完成了上两步操作后,现在已经能获取到用户的「最后活跃时间」了,不过为了保证数据的完整性,我们需要定期将 Redis 数据同步到数据库中,否则一旦 Redis 出问题或者执行了 Redis 清理操作,用户的「最后活跃时间」将会丢失。

我的方案是编写一个同步命令 SyncUserActivedTime,然后在计划任务里设置每 10 分钟运行该命令。以下是具体操作:

1). 运行以下命令添加 console

php artisan make:console SyncUserActivedTime --command=phphub:sync-user-actived-time

2). 在 app\Console\Commands\SyncUserActivedTime 添加逻辑代码

...

use Illuminate\Console\Command;

use App\Models\User;

use Cache;

class SyncUserActivedTime extends Command

{

protected $signature = 'phphub:sync-user-actived-time';

protected $description = 'Sync user actived time';

public function __construct()

{

parent::__construct();

}

public function handle()

{

// 注意这里获取的 Redis key 为 actived_time_for_update

// 获取完以后立马删除,这样就只更新需要更新的用户数据

$data = Cache::pull('actived_time_for_update'));

if (!$data) {

$this->error('Error: No Data!');

return false;

}

foreach ($data as $user_id => $last_actived_at) {

User::query()->where('id', $user_id)

->update(['last_actived_at' => $last_actived_at]);

}

$this->info('Done!');

}

}

3). 在 app/Console/Kernel.php 添加以下配置,生成 计划任务。

protected $commands = [

...

// 注册命令

Commands\SyncUserActivedTime::class,

];

protected function schedule(Schedule $schedule)

{

...

// 设置为每 10 分钟运行一次该命令。

$schedule->command('phphub:sync-user-actived-time')->everyTenMinutes();

}

获取用户的「最后活跃时间」

在 UserPresenter 添加以下方法

public function lastActivedAt()

{

$show_key = 'actived_time_data';

$show_data = Cache::get($show_key);

// 如果 Redis 中没有,则从数据库里获取,并同步到 Redis 中

if (!isset($show_data[$this->id])) {

$show_data[$this->id] = $this->last_actived_at;

Cache::forever($show_key, $show_data);

}

return $show_data[$this->id];

}

然后在需要展示的页面调用 lastActivedAt 即可,例如:

User::find(1)->present()->lastActivedAt;

如果你没有使用 present,可以将此方法写到 app/Models/User.php 中。

以上。

laravel redis mysql_Laravel 5.1 Redis 缓存配合 MySQL 数据库实现「用户最后活跃时间」功能...相关推荐

  1. redis和sqlserver数据同步_redis缓存和mysql数据库同步

    转载自:https://www.cnblogs.com/lanbo203/p/7494587.html 解决方案 一.对强一致要求比较高的,应采用实时同步方案,即查询缓存查询不到再从DB查询,保存到缓 ...

  2. wxpython配合MySQL数据库完成用户登录页面的设计

    文章目录 一.创建user表 2.给表添加数据 3.利用wxpython创建登录界面 4.执行结果如图 一.创建user表 # -*- coding: utf-8 -*- ""&q ...

  3. SpringCache与redis集成,优雅的缓存解决方案

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 来源:cnblogs.com/chenkeyu/p/8028781 ...

  4. 点赞模块设计:Redis缓存 + 定时写入数据库实现高性能点赞功能

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者:solocoder juejin.im/post/5bdc2 ...

  5. 带你100% 地了解 Redis 6.0 的客户端缓存

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 近日 Redis 6.0.0 GA 版本发布,这是 Redis 历 ...

  6. Redis总结(五)缓存雪崩和缓存穿透等问题

    前面讲过一些redis 缓存的使用和数据持久化.感兴趣的朋友可以看看之前的文章,http://www.cnblogs.com/zhangweizhong/category/771056.html .今 ...

  7. 十九、Redis 6.0 的客户端缓存

    一.为什么需要客户端缓存? 我们都知道,使用 Redis 进行数据的缓存的主要目的是减少对 MySQL 等数据库的访问,提供更快的访问速度,毕竟 <Redis in Action> 中提到 ...

  8. easyexcel写入数据为空_如何解决Redis缓存和MySQL数据一致性的问题?

    在高并发的业务场景下,数据库的性能瓶颈往往都是用户并发访问过大.所以,一般都使用redis做一个缓冲操作,让请求先访问到redis,而不是直接去访问MySQL等数据库.从而减少网络请求的延迟响应. 数 ...

  9. 分布式缓存redis 方案_Redis缓存和MySQL数据一致性方案详解

    在高并发的业务场景下,数据库大多数情况都是用户并发访问最薄弱的环节.所以,就需要使用redis做一个缓冲操作,让请求先访问到Redis,而不是直接访问MySQL等数据库. 这个业务场景,主要是解决读数 ...

最新文章

  1. 关于 Git 提交这些规范,你都遵守了吗?
  2. 学习AxureRP的成长之路
  3. CentOS 服务器安全设置
  4. linux 清空catalina.out日志 不需要重启tomcat(五种方法)【转】
  5. Apache Spark源码走读之3 -- Task运行期之函数调用关系分析
  6. VS2010解决闪退的方法
  7. 神秘的Windows7 Send To
  8. 公众号题库搜题对接(提供免费接口)
  9. 无线共享打印机无法连接服务器,“不能连接网络共享打印机”常见原因及处理方法:...
  10. 传统蓝牙BR/EDR的搜索Inquiry
  11. React | 受控组件(Controlled Component)与不受控组件(Uncontrolled Component)的区别
  12. 批处理创建隐秘的加密文件夹,是男人就把秘密藏起来
  13. 夯实基础 js数据类型
  14. 服务器上reportqueue文件夹,Reportqueue文件夹有什么用?如何设置电脑不生成Reportqueue文件...
  15. 可以让男人看一遍哭一遍的文章(转贴)
  16. linux u盘文件乱码,轻松解决Linux下U盘乱码的方法
  17. Creo5.0结构有限元仿真分析视频教程
  18. HTML+CSS+JS 学习笔记(一)———HTML(上)
  19. 搜狗权重查询 批量快速查询搜狗权重方法
  20. 电脑提示vcomp140.dll丢失怎么办?修复vcomp140.dll丢失的方法

热门文章

  1. iframe内联元素有白边原因_必看|番茄卷叶病发生的原因以及防治方法!
  2. linux手机投屏软件,无线投屏器如此多,到底哪一种才合适企业用?
  3. 语音通话框架_教资公告还没出,普通话测试又要改革?
  4. python清除字符串中间空格的方法
  5. Python 中函数(function)的用法
  6. python 鸭子类型及三大特性
  7. html播放完视频自动关闭,html视频播放完后跳转
  8. c语言fgetc()函数(从指定的流 stream 获取下一个字符(一个无符号字符),并把位置标识符往前移动)
  9. c/c++如何正确使用结构体?
  10. python绘制柱状图,如何改变柱状柱间距,如何设置横纵轴标签(绘制Intel Realsense D435深度误差柱状图)