为了方便没有用上redis做存储媒介,实际用途中应该是要用redis的有序集合以及hashMap来做数据排序以及数据存储的。下面代码主要是记录一个思路.

<?php

class Lruk
{

    private $maxMemberSize = 10;
    private $maxTimeLimit = 1800;
    private $lruNumber = 5;
    private $memberCache = [];
    private $memberCounts = [];
    private $memberTimes = [];

    public function memberVisit($memberId)
    {

        //累计用户的访问信息
        $this->incrMemberCount($memberId);

        //如果用户需要推入缓存
        if ($this->checkMemberStatus($memberId)) {
            $this->memberToCache($memberId);
        }
    }

    public function memberList()
    {
        return array_values($this->memberCache);
    }

    public function memberCount()
    {
        return $this->memberCounts;
    }

    public function memberTimes()
    {
        return $this->memberTimes;
    }

    private function incrMemberCount($memberId)
    {
        //如果已经在访问次数数组里
        if (isset($this->memberCounts[$memberId])) {

            //如果记录了用户访问时间
            if (isset($this->memberTimes[$memberId])) {

                if ($lastTime = $this->memberTimes[$memberId] ?: 0) {
                    //如果用户最后一次访问时间超过了间隔  则重置访问次数
                    if (time() - $lastTime >= $this->maxTimeLimit) {
                        $this->memberCounts[$memberId] = 1;
                    } else {
                        //累加次数
                        $this->memberCounts[$memberId] = $this->memberCounts[$memberId] + 1;
                    }
                } else {
                    $this->memberCounts[$memberId] = 1;
                }

                //未记录访问时间 则访问次数为1
            } else {
                $this->memberCounts[$memberId] = 1;
            }
        } else {
            //重置为1
            $this->memberCounts[$memberId] = 1;
        }

        $this->memberTimes[$memberId] = time();
    }

    /**
     * 获取用户的访问次数
     * @param $memberId
     * @return int|mixed
     */
    private function getMemberCount($memberId)
    {
        return $this->memberCounts[$memberId] ?? 0;
    }

    /**
     * 获取用户最后一次登录时间
     * @param $memberId
     * @return int|mixed
     */
    private function getMemberTime($memberId)
    {
        return $this->memberTimes[$memberId] ?? 0;
    }

    /**
     * 增加用户信息到缓存队列
     * @param $memberId
     * @return bool
     */
    private function memberToCache($memberId)
    {

        $count       = $this->getMemberCount($memberId);//获取用户访问次数
        $time        = $this->getMemberTime($memberId);//获取用户最后一次访问时间
        $memberCache = array_column($this->memberCache, null, 'memberId');
        $timeTxt     = date('Y-m-d H:i:s', $time);

        $memberCache[$memberId] = compact('memberId', 'count', 'time', 'timeTxt');

        //按时间倒序排列
        $times = array_column($memberCache, 'time', 'memberId');
        array_multisort($times, SORT_DESC, $memberCache);

        $this->memberCache = $memberCache;

        //如果到达最大长度  则删除尾部元素
        if (count($this->memberCache) > $this->maxMemberSize) {
            array_pop($this->memberCache);
        }
    }

    private function checkMemberStatus($memberId)
    {

        if (!isset($this->memberCache[$memberId])) {

            $memberCount = $this->memberCounts[$memberId] ?? 0;

            if ($memberCount >= $this->lruNumber) {
                return true;
            }
        }

        return false;
    }
}

$class = new Lruk;


for ($i = 0; $i <= 10000; $i++) {
    $memberId = random_int(1, 30);
    $class->memberVisit($memberId);
}
var_dump($class->memberList());

 

posted on 2020-06-03 15:55  沉默的土豆  阅读(463)  评论(0编辑  收藏  举报