为了方便没有用上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());