高性能Mysql(第3版)_网站点击计数器

网站访问量统计,自己实现思路:
每当用户访问页面,前端初始化方法自动调用后端接口,进行访问量统计,可以单独创建一个计数器表,使用独立的表可以帮助避免查询缓存失效。

udpate hit_counter set cnt=cnt+1 ;

但是当大量用户在同一时刻网站访问时,对于cnt字段的修改可能会造成短时间阻塞。
(问题在于,对于任何想要更新这一行的事务来说,这条记录上都有一个全局的互斥锁。这会使得这些事务只能串行执行。要获得更高的并发更新性能,也可以将计数器保存在多行中,每次随机选择一行进行更新。)
在阅读这本书时,提供了一种思路。
方法一:
若需要获取总的点击量结果(和日期无关),可以创建表字段。

create table hit_counter (slot tinyint unsigned not null, cnt int unsigned not null) ENGINE=INNODB

预先在这张表添加100行数据。现在选择一个随机的slot进行更新

update hit_counter set cnt=cnt+1 where slot =rand()*100

要获得统计结果,需要使用下面的聚合查询

select sum(cnt) from hit_counter;

(个人理解,以上也可以不用预先插入100行,将slot设置为主键,在slot字段插入时用rand()* 100,用 下面的 on duplicate key update,只是书中举栗这里插入100行便于理解下面的例子。 )
当需要进行每日或者每月(每隔一段时间)开始一个新的计数器,要这么设计表

create table daily_hit_counter(
day date not null,
slot tinyint unsigned not null,
cnt int unsigned not null,
primary key(day,slot)
) engine =innodb;

这里不用预先生成行,用

on duplicate key update

代替

insert into  daily_hit_counter(day,slot,cnt) values(current_date,rand()*100,1) on duplicate key update cnt=cnt+1;

这里day和slot构成联合主键,统计当日的点击量。
如果希望减少表的行数,以避免表变得太大,可以写一个周期执行的任务,合并所有结构到0号槽,并且删除其他所有的槽。

UPDATE dayily_hit_counter AS c
INNER JOIN ( SELECT DAY, sum( cnt ) AS cnt , min( slot ) AS mslot FROM daily_hit_counter GROUP BY DAY ) AS x USING ( DAY ) 
SET c.cnt =
IF
    ( c.slot = x.mslot, x.cnt, 0 ),
    c.slot =
IF
    ( c.slot = x.mslot, 0, c.slot );
    delete from daily_hit_counter where slot <> 0 and cnt=0;

为什么同样是rand()结果不一样。

本作品采用《CC 协议》,转载必须注明作者和本文链接
love ,live in the moment. 如果这篇文章对您有所帮助的话,请点一个赞,谢谢~
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!