zoukankan      html  css  js  c++  java
  • 0930MySQL中实现高性能高并发计数器方案(例如文章点击数)

    转自http://www.jb51.net/article/56656.htm

    这篇文章主要介绍了MySQL中实现高性能高并发计数器方案,本文中的计数器是指如文章的点击数、喜欢数、浏览次数等,需要的朋友可以参考下
     

    现在有很多的项目,对计数器的实现甚是随意,比如在实现网站文章点击数的时候,是这么设计数据表的,如:”article_id, article_name, article_content, article_author, article_view……在article_view中记录该文章的浏览量。诈一看似乎没有问题。对于小站,比如本博客,就是这么做的,因为小菜的博客难道会涉及并发问题吗?答案显而易见,一天没多少IP,而且以后不会很大。

    言归正传,对文章资讯类为主的项目,在浏览一个页面的时候不但要进行大量的查(查询上文的记录,已经所属分类的名字、热门文章资讯评论、TAG等),还要进行写操作(更新浏览数点击数)。把文章的详细内容和计数器放在一张表尽管对开发很方便,但是会造成数据库的压力过大(不然为什么大项目都要分库分表呢)。

    那么,分两张表存放就好了么?一张表存文章详细信息,另一张表单独存计数器。

    复制代码代码如下:

    CREATE TABLE `article_view`(
    `article_id` int(11) NOT NULL,
    `view` int(11) NOT NULL,
    PRIMARY KEY (`article_id`)
    )ENGINE=InnoDB;

    这种方式,虽然分担了文章表的压力,但是每当有一个进程请求更新的时候,都会产生全局的互斥锁,只能串行,不能并行。在高并发下会有较长的等待时间。

    另一种比较好的办法是对每一个文章的计数器不是一行,而是多行,比如吧,一百行。每次随机更新其中一行,该文章的浏览数就是所有行的和。

    复制代码代码如下:

    CREATE TABLE `article_view`(
    `article_id` int(11) NOT NULL,
    `pond` tinyint(4) NOT NULL COMMENT '池子,就是用来随机用的',
    `view` int(11) NOT NULL,
    PRIMARY KEY (`article_id`,`pond`)
    )ENGINE=InnoDB;

    小访问量的随机池子100个肯定多了,三五个足矣。每次访问的时候,随机一个数字(1-100)作为pond,如何该pond存在则更新view+1,否则插入,view=1。借助DUPLICATE KEY,不然在程序里是实现得先SELECT,判断一下再INSERT或者UPDATE。

    复制代码代码如下:

    INSERT INTO `article_view` (`article_id`, `pond`, `view`) VALUES (`123`, RAND()*100, 1) ON DUPLICATE KEY UPDATE `view`=`view`+1

    获取指定文章的总访问量的时候:

    复制代码代码如下:

    SELECT SUM(`view`) FROM `article_view` WHERE `article_id`='123'
     
    -- 最后针对如何减少表的行数 避免表太大

    如果希望减少表的行数,以避免表变得太大,可以写一个周期执行的任务,合并所有结果到0 号槽,并且删除所有其他的槽:
    UPDATE daily_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;

    PS:凡事都是双刃剑。为了更快的读我们通常要牺牲一些东西。在读比较多的表要加快读的速度,在写较多的表要加快写的速度。各自权衡。在加快读的速度的时候,我们牺牲的并不仅仅是写的性能,还有开发成本,开发变的更复杂,维护成本等。所以并不是读的速度越快越好,需要找一个平衡点。

  • 相关阅读:
    发布镜像
    实战Tomcat镜像
    Docker File介绍
    数据卷容器
    DockerFile
    具名、匿名、指定路径挂载
    实战MySQL
    SHELL 常用技巧
    CentOS6和7启动流程
    解决服务器openssh漏洞
  • 原文地址:https://www.cnblogs.com/qcfeng/p/5923830.html
Copyright © 2011-2022 走看看