laravel redis mysql_Laravel 5.1 Redis 缓存配合 MySQL 数据库实现「用户最后活跃时间」功能...
前言
今日給 PHPHub 開發(fā)了記錄用戶「最后活躍時(shí)間」的小功能,現(xiàn)在趁著熱乎將相關(guān)實(shí)現(xiàn)邏輯寫出來,歡迎大家指出不足。
基本思路
通過 Middleware 捕獲用戶的所有請(qǐng)求;
記錄用戶的請(qǐng)求時(shí)間,將數(shù)據(jù)放入緩存 (Redis) 中;
通過 Cron 每十分鐘將緩存 (Redis) 里的數(shù)據(jù)同步到數(shù)據(jù)庫中;
讀取數(shù)據(jù):先從 Redis 中讀取數(shù)據(jù),如 Redis 中沒有,則從數(shù)據(jù)庫中獲取數(shù)據(jù)并同步到 Redis 中。
下文中我將針對(duì)每一個(gè)步驟進(jìn)行詳細(xì)說明。
捕獲用戶的所有請(qǐng)求
只有捕獲用戶的所有請(qǐng)求,我們才能實(shí)時(shí)的記錄用戶的最后活躍時(shí)間。在這里我們通過 中間件 來實(shí)現(xiàn)此邏輯。以下是生成中間件的具體操作:
1). 運(yùn)行以下命令,生成 RecordLastActivedTime 中間件。
php artisan make:middleware RecordLastActivedTime
2). 在 app/Http/Kernel.php 中添加以下配置,將 RecordLastActivedTime 設(shè)置為全局中間件。
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()) {
// 在這里記錄用戶的訪問時(shí)間,下文將介紹此方法。
Auth::user()->recordLastActivedAt();
}
return $next($request);
}
}
這樣登錄用戶在訪問我們網(wǎng)站任何一個(gè)頁面時(shí),都會(huì)進(jìn)入到 RecordLastActivedTime 中,接下來我們將處理「記錄用戶請(qǐng)求時(shí)間」的邏輯。
記錄用戶的請(qǐng)求時(shí)間,將數(shù)據(jù)放入 Redis 中
現(xiàn)在,我們需要將用戶的「最后活躍時(shí)間」存放到 Redis 中,并且接下來的讀寫操作都在 Redis 里進(jìn)行,以減少數(shù)據(jù)庫的開銷。下面是具體操作:
1). 在 app/Models/User.php 中添加以下方法:
public function recordLastActivedAt()
{
$now = Carbon::now()->toDateTimeString();
// 這個(gè) Redis 用于數(shù)據(jù)庫更新,數(shù)據(jù)庫每同步一次則清空一次該 Redis 。
$update_key = 'actived_time_for_update';
$update_data = Cache::get($update_key);
$update_data[$this->id] = $now;
Cache::forever($update_key, $update_data);
// 這個(gè) Redis 用于讀取,每次要獲取活躍時(shí)間時(shí),先到該 Redis 中獲取數(shù)據(jù)。
$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 的數(shù)據(jù)結(jié)構(gòu)如下:
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 中間件中調(diào)用 recordLastActivedAt
class RecordLastActivedTime
{
public function handle($request, Closure $next)
{
if (Auth::check()) {
Auth::user()->recordLastActivedAt();
}
return $next($request);
}
}
至此,只要登錄的用戶每訪問一次網(wǎng)站,都會(huì)將其「最后活躍時(shí)間」記錄到 Redis 中。
定期將 Redis 里的數(shù)據(jù)同步到數(shù)據(jù)庫中
完成了上兩步操作后,現(xiàn)在已經(jīng)能獲取到用戶的「最后活躍時(shí)間」了,不過為了保證數(shù)據(jù)的完整性,我們需要定期將 Redis 數(shù)據(jù)同步到數(shù)據(jù)庫中,否則一旦 Redis 出問題或者執(zhí)行了 Redis 清理操作,用戶的「最后活躍時(shí)間」將會(huì)丟失。
我的方案是編寫一個(gè)同步命令 SyncUserActivedTime,然后在計(jì)劃任務(wù)里設(shè)置每 10 分鐘運(yùn)行該命令。以下是具體操作:
1). 運(yùn)行以下命令添加 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
// 獲取完以后立馬刪除,這樣就只更新需要更新的用戶數(shù)據(jù)
$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 添加以下配置,生成 計(jì)劃任務(wù)。
protected $commands = [
...
// 注冊(cè)命令
Commands\SyncUserActivedTime::class,
];
protected function schedule(Schedule $schedule)
{
...
// 設(shè)置為每 10 分鐘運(yùn)行一次該命令。
$schedule->command('phphub:sync-user-actived-time')->everyTenMinutes();
}
獲取用戶的「最后活躍時(shí)間」
在 UserPresenter 添加以下方法
public function lastActivedAt()
{
$show_key = 'actived_time_data';
$show_data = Cache::get($show_key);
// 如果 Redis 中沒有,則從數(shù)據(jù)庫里獲取,并同步到 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];
}
然后在需要展示的頁面調(diào)用 lastActivedAt 即可,例如:
User::find(1)->present()->lastActivedAt;
如果你沒有使用 present,可以將此方法寫到 app/Models/User.php 中。
以上。
總結(jié)
以上是生活随笔為你收集整理的laravel redis mysql_Laravel 5.1 Redis 缓存配合 MySQL 数据库实现「用户最后活跃时间」功能...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql创建读写账号_mysql创建读
- 下一篇: matlab中读文件的行数_Matlab