计数器的设计

应用场景

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

一般设计

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

  创建一个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倍,是因为少了等待锁的时间。

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

时间: 2024-08-25 05:12:54

计数器的设计的相关文章

微架构设计:微博计数器的设计

作者:@cydu 来源: http://qing.weibo.com/1639780001/61bd0ea133002460.html http://qing.weibo.com/1639780001/61bd0ea1330025sq.html 背景:  每一条微博的转发和评论背后都是一串串说不完的故事,但是今天主要讲的是 计数服务,计数服务详尽地记录着每条微博 被评论的次数 和 被转发的次数,当然也还有更多的喜怒哀乐都记录于此. 数据量:   微博总数量:  千亿级 而且每秒都在飞速增长中.每

计数器的设计与实现

仿真电路 程序仿真 or2a h_adder f_adder

计数器的原理,设计及verilog实现

若计数器由n个触发器组成,则计数器的位数为n,所能计数的最大模数为2的n次幂.以下为同步二进制加法计数器电路; 驱动方程:状态图 状态方程(此时的Q0,Q1为上一次状态值): 下例是同步4位2进制计数器的设计:该计数器具有异步清零,同步置数的功能,具有时钟端:clk;置数端:s;清零端:r:使能端:en;置数端: d[3:0];输出端:q [3:0];进位端:co. module counter(clk,co,q,r,s,en,d); input clk,r,s,en; // 时钟,清零端,置数

设计一个BCD码计数器。

BCD码计数器的定义: 对于机器语言,机器与人不同,为了让人更好的了解机器语言的数据输出,选用4位二进制数据表示十进制里的每位数据,这便是BCD码. 以下便是BCD码与十进制对应的码表 0-----------0000----------0x0 1-----------0001----------0x1 2-----------0010----------0x2 3-----------0011----------0x3 4-----------0100----------0x4 5------

06-BCD计数器设计与应用——小梅哥FPGA设计思想与验证方法视频教程配套文档

芯航线--普利斯队长精心奉献 ? 实验目的:1.掌握BCD码的原理.分类以及优缺点 ???????? 2.设计一个多位的8421码计数器并进行验证 ???????? 3.学会基本的错误定位以及修改能力 ???? 实验平台:无 实验原理: ????BCD码(Binary-Coded Decimal)又被称为二进码十进数.二-十进制代码是一种十进制的数字编码,用4位二进制数来表示十进制数中的0~9个十个数之一.BCD编码又可以分成有权码和无权码两种,其中有权码如:8421码.2421码以及5421等

简易数字钟设计

简易数字钟设计 一.摘要 信息时代,时间观念深入人心,所以掌握数字钟的设计具有一定的时代意义,并且使用Multisim进行分立元件设计数字钟,可以大大提升个人数字电路的素养. 设计思路是从上至下,先进行数字钟整体框架的设计,考虑各个子芯片的预留端口,再逐个设计各个子电路模块.最终完成了时钟显示,调时,闹钟,定点报时以及万年历的功能.并且总的控制点预留了新功能的接入口,这样子就可以十分方便的进行新功能的加入. 目录 简易数字钟设计... 1 一.摘要... 1 二.前期准备... 2 1.数电知识

大数据计算:如何仅用1.5KB内存为十亿对象计数

在Clearspring,我们从事统计数据.统计一组不同元素且数量很大的数据集时,是一个挑战. 为了更好地理解已经明确基数的大数据集的挑战,我们假设你的日志文件包含16个字符的ID,并且你想统计不同ID的数量.例如: 4f67bfc603106cb2 这16个字符需要用128位来表示.6万5千个ID将需要1MB的空间.我们每天收到30多亿条事件记录,每条记录都有一个ID.这些ID需要3840亿位或45GB的存储.而这仅仅是ID字段需要的空间.我们采取一种简单的方法获取日常事件记录中以ID为基数的

ServletContext是什么

什么是ServletContext?  ServletContext是一块所有客户都可以访问的共享的服务器端空间,和Session类似,就是名字和值 如何得到ServletContext的实例? this.ServletContext(); 如何添加属性到ServletContext中?  setAttribute(String name,Object obj); 如何删除ServletContext的属性?   removeAttribute(String name); 如何得到Servlet

Redis源码分析(二十六)--- slowLog和hyperloglog

今天学习的是是2个log的文件,2个文件的实现功能都超出我原本理解的意思.开始时我以为就是记录不同的类型的日志,后来才慢慢的明白了额,slowLog记录的是超时的查询记录,而hyperloglog其实跟日志一点关系都没有,好吧,我再一次傻眼了,他其实是一种基数统计算法,应该分开了看,hyper + loglog的计算.好,接下来,我们开始学习一下Redis代码中是如何实现的. slowLog的官方解释: /* Slowlog implements a system that is able to