成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Redis在項(xiàng)目中的應(yīng)用實(shí)例

libin19890520 / 3282人閱讀

摘要:在初步了解在中的應(yīng)用那么我們?cè)囅脒@樣的一個(gè)應(yīng)用場(chǎng)景一個(gè)文章或者帖子的瀏覽次數(shù)的統(tǒng)計(jì)如果只是每次增加一個(gè)瀏覽量就到數(shù)據(jù)庫(kù)新增一個(gè)數(shù)據(jù)如果請(qǐng)求來那個(gè)太大這對(duì)數(shù)據(jù)庫(kù)的消耗也就不言而喻了吧那我們是不是可以有其他的解決方案這里的解決方案就是即使你的網(wǎng)

在初步了解RedisLaravel中的應(yīng)用 那么我們?cè)囅脒@樣的一個(gè)應(yīng)用場(chǎng)景 一個(gè)文章或者帖子的瀏覽次數(shù)的統(tǒng)計(jì) 如果只是每次增加一個(gè)瀏覽量

就到數(shù)據(jù)庫(kù)新增一個(gè)數(shù)據(jù) 如果請(qǐng)求來那個(gè)太大這對(duì)數(shù)據(jù)庫(kù)的消耗也就不言而喻了吧 那我們是不是可以有其他的解決方案

這里的解決方案就是 即使你的網(wǎng)站的請(qǐng)求量很大 那么每次增加一個(gè)訪問量就在緩存中去進(jìn)行更改 至于刷新Mysql數(shù)據(jù)庫(kù)可以自定義為

多少分鐘進(jìn)行刷新一次或者訪問量達(dá)到一定數(shù)量再去刷新數(shù)據(jù)庫(kù) 這樣數(shù)據(jù)也是準(zhǔn)確的 效率也比直接每次刷新數(shù)據(jù)庫(kù)要高出許多了

既然給出了相應(yīng)的解決方案 我們就開始實(shí)施

我們以一篇帖子的瀏覽為例 我們先去創(chuàng)建對(duì)應(yīng)的控制器

$ php artisan make:controller PostController

再去生成需要用到的 Model

$ php artisan make:model Post -m

填寫posts的遷移表的字段內(nèi)容

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

還有就是我們測(cè)試的數(shù)據(jù)的Seeder填充數(shù)據(jù)

$factory->define(AppPost::class, function (FakerGenerator $faker) {
    return [
        "title" => $faker->sentence,
        "content" => $faker->paragraph,
        "view_count" => 0
    ];
});

定義帖子的訪問路由

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

當(dāng)然我們還是需要去寫我們?cè)L問也就是瀏覽事件的(在app/providers/EventServiceProvider中定義)

protected $listen = [
        "AppEventsPostViewEvent" => [
//            "AppListenersEventListener",
            "AppListenersPostEventListener",
        ],
    ];

執(zhí)行事件生成監(jiān)聽

$ php artisan event:generate

之前定義了相關(guān)的路由方法 現(xiàn)在去實(shí)現(xiàn)一下:

public function showPost(Request $request,$id)
{
    //Redis緩存中沒有該post,則從數(shù)據(jù)庫(kù)中取值,并存入Redis中,該鍵值key="post:cache".$id生命時(shí)間5分鐘
    $post = Cache::remember("post:cache:".$id, $this->cacheExpires, function () use ($id) {
        return Post::whereId($id)->first();
    });

    //獲取客戶端請(qǐng)求的IP
    $ip = $request->ip();
    
    //觸發(fā)瀏覽次數(shù)統(tǒng)計(jì)時(shí)間
    event(new PostViewEvent($post, $ip));

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

這里看的出來就是以Redis作為緩存驅(qū)動(dòng) 同樣的 會(huì)獲取獲取的ip目的是防止同一個(gè)ip多次刷新來增加瀏覽量

同樣的每次瀏覽會(huì)觸發(fā)我們之前定義的事件 傳入我們的postid參數(shù)

Redis的key的命名以:分割 這樣可以理解為一個(gè)層級(jí)目錄 在可視化工具里就可以看的很明顯了

接下來就是給出我們的posts.show的視圖文件



    
    
    
    Bootstrap Template
    
    
    


Title:{{$post->title}}

Content:{{$post->content}}

初始化我們的事件就是接收一下這些參數(shù)即可

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("channel-name");
    }
}

最主要的還是編寫我們的監(jiān)聽事件:

class PostEventListener
{
    /**
     * 一個(gè)帖子的最大訪問數(shù)
     */
    const postViewLimit = 20;

    /**
     * 同一用戶瀏覽同一個(gè)帖子的過期時(shí)間
     */
    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秒時(shí)間內(nèi),同一IP訪問多次,僅僅作為1次訪問量
        if($this->ipViewLimit($id, $ip)){
            //一個(gè)IP在300秒時(shí)間內(nèi)訪問第一次時(shí),刷新下該篇post的瀏覽量
            $this->updateCacheViewCount($id, $ip);
        }
    }

    /**
     * 限制同一IP一段時(shí)間內(nèi)得訪問,防止增加無(wú)效瀏覽次數(shù)
     * @param $id
     * @param $ip
     * @return bool
     */
    public function ipViewLimit($id, $ip)
    {
        $ipPostViewKey    = "post:ip:limit:".$id;
        //Redis命令SISMEMBER檢查集合類型Set中有沒有該鍵,Set集合類型中值都是唯一
        $existsInRedisSet = Redis::command("SISMEMBER", [$ipPostViewKey, $ip]);
        //如果集合中不存在這個(gè)建 那么新建一個(gè)并設(shè)置過期時(shí)間
        if(!$existsInRedisSet){
            //SADD,集合類型指令,向ipPostViewKey鍵中加一個(gè)值ip
            Redis::command("SADD", [$ipPostViewKey, $ip]);
            //并給該鍵設(shè)置生命時(shí)間,這里設(shè)置300秒,300秒后同一IP訪問就當(dāng)做是新的瀏覽量了
            Redis::command("EXPIRE", [$ipPostViewKey, self::ipExpireSec]);
            return true;
        }
        return false;
    }

    /**
     * 達(dá)到要求更新數(shù)據(jù)庫(kù)的瀏覽量
     * @param $id
     * @param $count
     */
    public function updateModelViewCount($id, $count)
    {
        //訪問量達(dá)到300,再進(jìn)行一次SQL更新
        $post = Post::find($id);
        $post->view_count += $count;
        $post->save();
    }

    /**
     * 不同用戶訪問,更新緩存中瀏覽次數(shù)
     * @param $id
     * @param $ip
     */
    public function updateCacheViewCount($id, $ip)
    {
        $cacheKey = "post:view:".$id;
        //這里以Redis哈希類型存儲(chǔ)鍵,就和數(shù)組類似,$cacheKey就類似數(shù)組名  如果這個(gè)key存在
        if(Redis::command("HEXISTS", [$cacheKey, $ip])){
            //哈希類型指令HINCRBY,就是給$cacheKey[$ip]加上一個(gè)值,這里一次訪問就是1
            $save_count = Redis::command("HINCRBY", [$cacheKey, $ip, 1]);
            //redis中這個(gè)存儲(chǔ)瀏覽量的值達(dá)到30后,就去刷新一次數(shù)據(jù)庫(kù)
            if($save_count == self::postViewLimit){
                $this->updateModelViewCount($id, $save_count);
                //本篇post,redis中瀏覽量刷進(jìn)MySQL后,就把該篇post的瀏覽量清空,重新開始計(jì)數(shù)
                Redis::command("HDEL", [$cacheKey, $ip]);
                Redis::command("DEL", ["laravel:post:cache:".$id]);
            }
        }else{
            //哈希類型指令HSET,和數(shù)組類似,就像$cacheKey[$ip] = 1;
            Redis::command("HSET", [$cacheKey, $ip, "1"]);
        }
    }
}

最后可以通過我們的工具查看具體效果

相關(guān)鏈接

Redis 命令

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/25604.html

相關(guān)文章

  • Redis的KEYS命令引起宕機(jī)事件

    摘要:最近的互聯(lián)網(wǎng)線上事故發(fā)生比較頻繁,年月號(hào)順豐發(fā)生了一起線上刪庫(kù)事件,在這里就不介紹了。最后的最后,線上操作的任何一條命令,再小心也不為過,因?yàn)橛捎谀愕囊粋€(gè)符號(hào)而引起的事故可能是你所承擔(dān)不起的。 摘要: 使用 Redis 的開發(fā)者必看,吸取教訓(xùn)?。? 原文:Redis 的 KEYS 命令引起 RDS 數(shù)據(jù)庫(kù)雪崩,RDS 發(fā)生兩次宕機(jī),造成幾百萬(wàn)的資金損失 作者:陳浩翔 Fundebu...

    zoomdong 評(píng)論0 收藏0
  • Redis的KEYS命令引起宕機(jī)事件

    摘要:最近的互聯(lián)網(wǎng)線上事故發(fā)生比較頻繁,年月號(hào)順豐發(fā)生了一起線上刪庫(kù)事件,在這里就不介紹了。最后的最后,線上操作的任何一條命令,再小心也不為過,因?yàn)橛捎谀愕囊粋€(gè)符號(hào)而引起的事故可能是你所承擔(dān)不起的。 摘要: 使用 Redis 的開發(fā)者必看,吸取教訓(xùn)?。? 原文:Redis 的 KEYS 命令引起 RDS 數(shù)據(jù)庫(kù)雪崩,RDS 發(fā)生兩次宕機(jī),造成幾百萬(wàn)的資金損失 作者:陳浩翔 Fundebu...

    ixlei 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<