做日活与月活的统计分析
寻求了好多解决方案最后选择了采用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);
}
做一下记录,今天北京说有暴雨建议单位居家办公。。。结果我司无动于衷呀。。。












网友评论