码迷,mamicode.com
首页 > 其他好文 > 详细

计数器的设计

时间:2015-02-13 12:58:05      阅读:124      评论:0      收藏:0      [点我收藏+]

标签:

应用场景

  计数器在现在的网站是很经常出现的,如计算该网站的点击率、该文件的下载次数、网站的访问量等。

一般设计

  在不考虑其他业务的情况下,只考虑实现一个计数器的思路。我们会创建一张独立的表存储计数值。

  创建一个counter表来表示计数器:

CREATE TABLE counter (
    count INT UNSIGNED NOT NULL
);

  初始化:

INSERT INTO counter VALUES(0);

  计数器工作sql:

UPDATE counter SET count = count + 1;

  测试100个线程并发工作执行语句10次:

mysqlslap -u root -p  --concurrency=100 --iterations=100 --create-schema=‘test‘ --query=‘update counter set count = count + 1‘ --debug-info

  结果:

Benchmark
        Average number of seconds to run all queries: 0.101 seconds
        Minimum number of seconds to run all queries: 0.026 seconds
        Maximum number of seconds to run all queries: 0.906 seconds
        Number of clients running queries: 100
        Average number of queries per client: 1


User time 0.15, System time 0.84
Maximum resident set size 7024, Integral resident set size 0
Non-physical pagefaults 53513, Physical pagefaults 0, Swaps 0
Blocks in 0 out 0, Messages in 0 out 0, Signals 0
Voluntary context switches 59935, Involuntary context switches 6357

优化设计

  对于在现在高并发的时代,影响着这个计数器的并发性的是一个mutex,为了保证事务的正确性,只能加锁,一加锁这些事务只能串行运行。为了获得高并发性能,我将计数的数据保存在多行中,每次执行都不一定会锁在同一行,导致等待。

  创建表:

CREATE TABLE counter (
    id TINYINT UNSIGNED NOT NULL PRIMARY KEY,
    count INT UNSIGNED NOT NULL
);

   初始化:

CREATE PROCEDURE loadCounter(number INT UNSIGNED)
BEGIN
DECLARE i INT UNSIGNED DEFAULT 0;
WHILE i < number DO
INSERT INTO counter SELECT i, 0;
COMMIT;
SET i = i + 1;
END WHILE;
END;

CALL loadCounter(100);

   更新计数器:

UPDATE counter SET count = count + 1 WHERE id = FLOOR(RAND()*100);

  获取计数值:

SELECT SUM(count) FROM counter;

  测试100个线程并发工作执行语句10次:

mysqlslap -u root -p --concurrency=100 --iterations=100 --create-schema=‘test‘ --query=‘UPDATE counter SET count = count + 1 WHERE id = FLOOR(RAND()*100);‘ --debug-info    

  结果:

Benchmark
        Average number of seconds to run all queries: 0.091 seconds
        Minimum number of seconds to run all queries: 0.022 seconds
        Maximum number of seconds to run all queries: 0.347 seconds
        Number of clients running queries: 100
        Average number of queries per client: 1


User time 0.20, System time 0.83
Maximum resident set size 5260, Integral resident set size 0
Non-physical pagefaults 53218, Physical pagefaults 1, Swaps 0
Blocks in 8 out 0, Messages in 0 out 0, Signals 0
Voluntary context switches 64740, Involuntary context switches 1588

优化思路

  我们对比两者的测试结果,发现优化后的设计在执行上是有了提高,很执行sql的最长时间中,优化后时间降下了2倍,是因为少了等待锁的时间。

  一般设计的并发性差的原因是因为我们的执行目标都在一条记录上,多个线程同时执行的话,很容易产生互斥。优化设计将目标扩散到了多个记录中。事务的等待时间久大大减少了,效率就高了很多。

计数器的设计

标签:

原文地址:http://www.cnblogs.com/xujianguo501/p/4280505.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!