ホームページ >バックエンド開発 >PHPチュートリアル >LaravelプロジェクトにおけるRedisの実践例

LaravelプロジェクトにおけるRedisの実践例

巴扎黑
巴扎黑オリジナル
2017-08-12 11:50:212215ブラウズ

この記事では、Laravel プロジェクトにおける Redis のアプリケーションに関する関連情報を、サンプルコードを通じて詳しく紹介します。Laravel を必要とする人にとって、学習の参考となる価値があります。以下の編集者をフォローして、一緒に学びましょう。

はじめに

この記事では主に Laravel プロジェクトにおける Redis の適用例を紹介し、参考と学習のために共有します。以下では多くを述べませんが、詳細な紹介を見てみましょう:

「Laravel での Redis のアプリケーションについて予備的に理解しましょう」では、記事または投稿のビュー数の統計が毎回 1 ビューだけ増加する場合を想像してみましょう。リクエストが大きすぎる場合、データベースの消費量は自明のことですよね。Web サイトに大量のリクエストがある場合でも、そのたびに別の解決策を講じることはできますか?変更点 MySQL データベースの更新については、

何分間更新するか、またはデータベースを更新する前に特定の回数に達するまでの訪問数をカスタマイズできます。これにより、データが正確になります。毎回データベースを直接更新するよりも効率がはるかに高くなります

これで、対応するソリューションの実装を開始します

投稿の閲覧を例として、まず対応するコントローラーを作成します

$ php artisan make:controller PostController

そして、使用する必要があるモデルを生成します


$ php artisan make:model Post -m

移行テーブルのフィールドコンテンツ


Schema::create('posts', function (Blueprint $table) {
 $table->increments('id');
 $table->string("title");
 $table->string("content");
 $table->integer('view_count')->unsigned();
 $table->timestamps();
});

とテストデータのシーダー充填データ


$factory->define(App\Post::class, function (Faker\Generator $faker) {
 return [
 'title' => $faker->sentence,
 'content' => $faker->paragraph,
 'view_count' => 0
 ];
});
を投稿します

投稿のアクセスルートを定義します


Route::get('/post/{id}', 'PostController@showPost');

もちろん、イベント(app/providers/EventServiceProviderで定義)を参照するアクセスを記述する必要があります


protected $listen = [
 'App\Events\PostViewEvent' => [
//  'App\Listeners\EventListener',
  'App\Listeners\PostEventListener',
 ],
 ];

イベント生成監視を実行します


$ php artisan event:generate

関連するルーティング メソッドは前に定義されています。次に、それを実装してください:


public function showPost(Request $request,$id)
{
 //Redis缓存中没有该post,则从数据库中取值,并存入Redis中,该键值key='post:cache'.$id生命时间5分钟
 $post = Cache::remember('post:cache:'.$id, $this->cacheExpires, function () use ($id) {
 return Post::whereId($id)->first();
 });

 //获取客户端请求的IP
 $ip = $request->ip();
 
 //触发浏览次数统计时间
 event(new PostViewEvent($post, $ip));

 return view('posts.show', compact('post'));
}

ここで確認できます。キャッシュ ドライバーとして Redis を使用すると、同じ IP が取得されるのを防ぐこともできます。ビュー数を増やすために複数回更新されます


同様に、閲覧するたびに前に定義したイベントがトリガーされ、それが投稿パラメータと ID パラメータに渡されます

Redis のキーには Split という名前が付いています。これは理解できます。視覚化ツールで明確に確認できる階層ディレクトリとして表示されます


次のステップは、投稿のビュー ファイルを提供することです。show

<html lang="en">
<head>
 <meta charset="utf-8">
 <meta http-equiv="X-UA-Compatible" content="IE=edge">
 <meta name="viewport" content="width=device-width, initial-scale=1">
 <title>Bootstrap Template</title>
 <!-- 新 Bootstrap 核心 CSS 文件 -->
 <link rel="stylesheet" href="//cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="external nofollow" >
 <style>
 html,body{
  width: 100%;
  height: 100%;
 }
 *{
  margin: 0;
  border: 0;
 }
 .jumbotron{
  margin-top: 10%;
 }
 .jumbotron>span{
  margin: 10px;
 }
 </style>
</head>
<body>
<p class="container">
 <p class="row">
 <p class="col-xs-12 col-md-12">
  <p class="jumbotron">
  <h1>Title:{{$post->title}}</h1>
  <span class="glyphicon glyphicon-eye-open" aria-hidden="true"> {{$post->view_count}} views</span>
  <p>Content:{{$post->content}}</p>
  </p>
 </p>
 </p>
</p>

<!-- jQuery文件-->
<script src="//cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>
<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
<script src="//cdn.bootcss.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<script>

</script>
</body>
</html>

イベントを初期化するには、これらのパラメーターを受け取ることです


class PostViewEvent
{
 use Dispatchable, InteractsWithSockets, SerializesModels;

 public $ip;
 public $post;


 /**
 * PostViewEvent constructor.
 * @param Post $post
 * @param $ip
 */
 public function __construct(Post $post, $ip)
 {
 $this->post = $post;
 $this->ip = $ip;
 }

 /**
 * Get the channels the event should broadcast on.
 *
 * @return Channel|array
 */
 public function broadcastOn()
 {
 return new PrivateChannel(&#39;channel-name&#39;);
 }
}

最も重要なことは、監視イベントを記述することです:


class PostEventListener
{
 /**
 * 一个帖子的最大访问数
 */
 const postViewLimit = 20;

 /**
 * 同一用户浏览同一个帖子的过期时间
 */
 const ipExpireSec = 200;

 /**
 * Create the event listener.
 *
 */
 public function __construct()
 {

 }


 /**
 * @param PostViewEvent $event
 */
 public function handle(PostViewEvent $event)
 {
 $post = $event->post;
 $ip = $event->ip;
 $id = $post->id;
 //首先判断下ipExpireSec = 200秒时间内,同一IP访问多次,仅仅作为1次访问量
 if($this->ipViewLimit($id, $ip)){
  //一个IP在300秒时间内访问第一次时,刷新下该篇post的浏览量
  $this->updateCacheViewCount($id, $ip);
 }
 }

 /**
 * 限制同一IP一段时间内得访问,防止增加无效浏览次数
 * @param $id
 * @param $ip
 * @return bool
 */
 public function ipViewLimit($id, $ip)
 {
 $ipPostViewKey = &#39;post:ip:limit:&#39;.$id;
 //Redis命令SISMEMBER检查集合类型Set中有没有该键,Set集合类型中值都是唯一
 $existsInRedisSet = Redis::command(&#39;SISMEMBER&#39;, [$ipPostViewKey, $ip]);
 //如果集合中不存在这个建 那么新建一个并设置过期时间
 if(!$existsInRedisSet){
  //SADD,集合类型指令,向ipPostViewKey键中加一个值ip
  Redis::command(&#39;SADD&#39;, [$ipPostViewKey, $ip]);
  //并给该键设置生命时间,这里设置300秒,300秒后同一IP访问就当做是新的浏览量了
  Redis::command(&#39;EXPIRE&#39;, [$ipPostViewKey, self::ipExpireSec]);
  return true;
 }
 return false;
 }

 /**
 * 达到要求更新数据库的浏览量
 * @param $id
 * @param $count
 */
 public function updateModelViewCount($id, $count)
 {
 //访问量达到300,再进行一次SQL更新
 $post = Post::find($id);
 $post->view_count += $count;
 $post->save();
 }

 /**
 * 不同用户访问,更新缓存中浏览次数
 * @param $id
 * @param $ip
 */
 public function updateCacheViewCount($id, $ip)
 {
 $cacheKey = &#39;post:view:&#39;.$id;
 //这里以Redis哈希类型存储键,就和数组类似,$cacheKey就类似数组名 如果这个key存在
 if(Redis::command(&#39;HEXISTS&#39;, [$cacheKey, $ip])){
  //哈希类型指令HINCRBY,就是给$cacheKey[$ip]加上一个值,这里一次访问就是1
  $save_count = Redis::command(&#39;HINCRBY&#39;, [$cacheKey, $ip, 1]);
  //redis中这个存储浏览量的值达到30后,就去刷新一次数据库
  if($save_count == self::postViewLimit){
  $this->updateModelViewCount($id, $save_count);
  //本篇post,redis中浏览量刷进MySQL后,就把该篇post的浏览量清空,重新开始计数
  Redis::command(&#39;HDEL&#39;, [$cacheKey, $ip]);
  Redis::command(&#39;DEL&#39;, [&#39;laravel:post:cache:&#39;.$id]);
  }
 }else{
  //哈希类型指令HSET,和数组类似,就像$cacheKey[$ip] = 1;
  Redis::command(&#39;HSET&#39;, [$cacheKey, $ip, &#39;1&#39;]);
 }
 }
}

最後に、ツールを使用して具体的な効果を確認できます


以上がLaravelプロジェクトにおけるRedisの実践例の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。