程序员

laravel + redis 实现月活与日活统计

2020-08-12  本文已影响0人  咯噔爸比

做日活与月活的统计分析

寻求了好多解决方案最后选择了采用redis BitMap 的方式来做操作

BitMap是什么

就是通过一个bit位来表示某个元素对应的值或者状态,其中的key就是对应元素本身。我们知道8个bit可以组成一个Byte,所以bitmap本身会极大的节省储存空间。存储1亿个用户的状态的话大约是12M的大小||大概的空间占用计算公式是:(数量/8/1024/1024)MB
简单说明,每一个bit位代表着一个用户的id 有活跃就记为1 没有活跃就记为0
如果想要详细了解的话:需要了解一下位运算相关的知识 https://www.sohu.com/a/300039010_114877

laravel 进行日活统计流程中事件的相关应用

1.注册事件和监听器 到 EventServiceProvider中

 protected $listen = [
        Registered::class => [
            SendEmailVerificationNotification::class,
        ],
        'App\Events\ActiveLog' => [
            'App\Listeners\SendActive@log',
        ],
        'App\Events\StatisticActive' => [
            'App\Listeners\SendActive@index',
        ],
    ];

2.生成事件 & 监听器

执行命令 php artisan event:generate

3.定义事件创建事件实例

#event文件夹下
class ActiveLog
{
    use Dispatchable, InteractsWithSockets, SerializesModels;
    public $uid;

    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct($uid)
    {
        //
        $this->uid = $uid;
    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return \Illuminate\Broadcasting\Channel|array
     */
    public function broadcastOn()
    {
        return new PrivateChannel('channel-name');
    }
}
class SendActive
{
    public $_prefix_key='user_action::';
    public $_redis =null;
    /**
     * Create the event listener.
     *
     * @return void
     */
    public function __construct()
    {
        //
        $this->_redis=app('redis.connection');
    }

    /**
     * Handle the event.
     *
     * @param  StatisticActive  $event
     * @return void
     */
    public function handle(StatisticActive $event)
    {
        //
        //dd($event);
    }
    //统计分析 按日统计按月统计
    public function index(StatisticActive $event){
        //日统计
        $this->day();
        //月统计
        $this->month();

    }
    //记录日志
    public function log(ActiveLog $event){
        $userid=$event->uid;
        $key=date('Ymd');
        $key=$this->_prefix_key.$key;
        //记录日活数据
        $this->_redis->setbit($key,$userid,1);

    }
    //每日执行一次
    public function day(){
        //计算日活跃写入数据库
        $day = date('Ymd',strtotime("-1 days"));
        $key =$this->_prefix_key.$day;
        $total=$this->_redis->bitCount($key);
        DB::table('statistics_active')->insert(['day'=>$day,'total'=>$total??0]);
    }
    //按月计算
    public function month(){
        $days = date('t', strtotime("-1 days"));
        $start_time = strtotime(date('Y-m-01',strtotime("-1 days")));  //获取本月第一天时间戳
        $month = date('Ym',$start_time);
        $key=$month.'month_active';
        $this->_redis->del($key);
        for($i=0;$i<$days;$i++){
            $str = $this->_prefix_key.date('Ymd',$start_time+$i*86400); //每隔一天赋值给数组
            $this->_redis->bitOp('or',$key,$key,$str);
        }
        $total=$this->_redis->bitCount($key);
        $this->_redis->del($key);
        DB::table('statistics_active')->insert(['day'=>$month,'total'=>$total??0]);
    }
}

4.事件调用

#我方在中间件中用户访问的时候增加这个记录的
if (!empty($userid)){
                event(new ActiveLog($userid));
                $this->addlog($userid);
            }

做一下记录,今天北京说有暴雨建议单位居家办公。。。结果我司无动于衷呀。。。

上一篇 下一篇

猜你喜欢

热点阅读