如何设计一个可伸缩的计数系统

很多应用程序都有通知或系统消息的功能模块,如果有新消息会以红点或消息条数在某个显眼位置展示给用户,这是计数系统使用场景之一。应用内部,比如微博,每个用户有自己发送微博数量,微博评价数等需要计数的需求,这也是计数系统常见的使用场景。将普遍需要的计数功能独立出一个单独的模块或系统,有利用系统的扩展,所以本文将讨论下如何构建一个可伸缩的计数系统。

1. 先对上述计数常见使用场景简要分析。第一种情况,如果有新消息,应用会显示消息条数或直接显示红点,比如CSDN通知栏的做法,这种场景需要的是消息的增量信息。第二种情况,比如微博计数统计,每个微博的转发数,评价数,这些场景需要的是消息的全量信息。因此,我们要设计的计数系统需要支持全量和增量的统计,还需要支持对不同类型消息的计数。

2. 表结构设计。从需求中我们可以抽象出一个item概念,它表示一个消息类型及该消息类型支持的key数量,对全量和增量支持的flag,表结构如下:

CREATE TABLE `item` (
`item_type` varchar(64) NOT NULL,
`key_size` tinyint(2) NOT NULL DEFAULT '0',
`comment` varchar(255) DEFAULT NULL,
`flag` tinyint(8) DEFAULT '0',
PRIMARY KEY (`item_type`,`key_size`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

出于可用性的考虑,我们没有将增量,全量作为消息类型的一个属性而是作为扩展的维度直接关联到具体的消息类型,具体做法是:如果建立一个item_type为t,key_size为2的消息,那我们同时会创建amount_t.2delta_t.2的两张表,这样即表示了增量,全量的概念,也通过分表的做法提高系统性能。

3. 缓存的使用。 由于计数系统操作相当频繁,为了保证性能采用缓存是必然的。常见的NoSQL数据库,比如MongoDB,Redis都可以满足我们的需求。它们一般都提供分布式,原子性的incr和decr操作,非常适合实现计数系统。如果采用memcached作为缓存层的话,需要注意memcached底层对数值的处理。Memcached底层是采用字符串来存放数值类型的,所以初始化缓存时需要将数值转换为字符串形式,否则某些memcached客户端会将底层的字符串展开为数值(ASCII码值)并返回,比如spymemcached客户端,这是踩过的坑

缓存中key如何定义?可以将类型及具体的key组合成缓存中的key,比如上述item的一个keys为10,20的具体类型,那缓存中的key可以定义为amount:t.2:10,20,delta:t.2:10,20,该具体类型的计数就是缓存中key对应的value。由于增量数据基本都是瞬时数据,更新比较频繁,可以根据场景决定是否要将这些数据持久化到数据库中。

4. 计数获取和更新。通过对计数类型分表,系统扩展性有了提高,但另一方面计数的获取就复杂化了。如果需要获取不同类型的计数,那就要跨越多张表。循环查询每张表是相当耗时的,所以常见的优化方案是采用多线程。对不同类型计数的更新需要注意先排序然后更新,以避免发生数据库死锁,另外更新操作可以异步处理。

5. 对外接口提供。 采用RESTful + JSON提供get和update接口。

时间: 2024-10-28 15:56:04

如何设计一个可伸缩的计数系统的相关文章

设计一个查询词提示系统

查询词提升是现代搜索引擎中广泛使用的一种技术,当用户输入查询词前缀时,会给出一系列相关的查询词推荐,例如在搜索框内输入"中国",会提升"中国好声音","中国银行", "中国联通"等,尝试设计一个查询词提示系统,回答以下问题: 1.给定一个查询词集合,用何种数据结构和算法来构建最基本的提示系统?要求输入中文和拼音都能正常工作 2.用户输入的前缀下可能有很多可提示的查询词,如何对这些查询词进行排序,将用户选择概率更高的词放在前面?

从研发人的角度评判怎样设计一个好的DCS系统

相信从事自动化或控制系统的同仁,应该了解Distributed Control System(简称DCS)的基本功能及其在工控行业的作用.从工程应用的角度,一个完整的DCS系统主要包括三个部分:HMI人机交互层.控制站层.仪表与执行机构层. HMI主要包括工程师站.监控站.历史站等,主要在具有较高稳定的PC上安装相应的软件构成.控制站层,主要实现相应的控制算法与逻辑,并通过相应的IO卡件采集数据和发送指令.仪表与执行机构,主要由各个厂家的智能变送器.电动机等组成. 由于仪表与执行机构,厂家众多,

深度学习:从头设计一个TensorFlow3一样的新一代深度学习系统,到底需要把握哪些要点?

深度学习工具潮流滚滚,各种工具层出不穷.也有各种文章从易用性,可移植性,灵活性和效率方面对于各个系统进行比较.这篇文章希望从系统设计上面来讲来回答这个讨论这个问题:如果想到从头设计一个TensorFlow3一样的新一代深度学习系统,到底需要把握哪些要点. 计算单元:从layer abstraction到operator 大家熟悉的第一代深度学习系统,以cuda-convnet21和caffe为代表.这些系统主要的一大特点是提出了一个以深度学习计算层次layer为基本单元的计算单位.不同的laye

Linux内核设计第三周——构造一个简单的Linux系统

Linux内核设计第三周 ——构造一个简单的Linux系统 一.知识点总结 计算机三个法宝: 存储程序计算机 函数调用堆栈 中断 操作系统两把宝剑: 中断上下文的切换 进程上下文的切换 linux内核源代码分析 arch/目录保存支持多种CPU类型的源代码 其中的关键目录包括:Documentation.drivers.firewall.fs(文件系统).include init目录:含有main.c,内核启动相关的代码基本都在init目录下 start_kernal()函数为启动函数,初始化内

如何设计一个RPC系统

版权声明:本文由韩伟原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/162 来源:腾云阁 https://www.qcloud.com/community RPC是一种方便的网络通信编程模型,由于和编程语言的高度结合,大大减少了处理网络数据的复杂度,让代码可读性也有可观的提高.但是RPC本身的构成却比较复杂,由于受到编程语言.网络模型.使用习惯的约束,有大量的妥协和取舍之处.本文就是通过分析几种流行的RPC实现案例,提供

Linux下一个简单的日志系统的设计及其C代码实现

1.概述 在大型软件系统中,为了监测软件运行状况及排查软件故障,一般都会要求软件程序在运行的过程中产生日志文件.在日志文件中存放程序流程中的一些重要信息, 包括:变量名称及其值.消息结构定义.函数返回值及其执行情况.脚本执行及调用情况等.通过阅读日志文件,我们能够较快地跟踪程序流程,并发现程序问题. 因此,熟练掌握日志系统的编写方法并快速地阅读日志文件,是对一个软件开发工程师的基本要求. 本文详细地介绍了Linux下一个简单的日志系统的设计方法,并给出了其C代码实现.本文为相关开发项目Linux

连载:告诉你如何设计一个日访问量千万级别的系统,谈oracle的高级设计和开发(2)

接下来正式开篇讲解在实际中大型项目中oracle的高级设计及开发的内容,以下讲解的oracle内容以及示例程序都是基于oracle11R2. 为了防止脱离实际地搞一堆理论,本人尽量用实际工作中的例子来说明问题,当然一些必要的理论有时候还是需要讲解,因为说的内容是高级设计及开发,入门级的SQL以及数据库概念将不会做详细讲解. 绝大多数IT项目,都是围绕数据库进行各种业务的,所以也有人将这类项目称为数据库项目,也就是说数据库是重点,有过项目设计经验的都知道,好的数据库设计,可以让开发和维护变得简单,

设计一个可扩展的用户登录系统

在Web系统中,用户登录是最基本的功能.如何设计一个可扩展的用户登录系统呢?本文结合实际案例对用户登录系统设计进行多维度的讲解,帮助各设计者在应用中将复杂变得简单. 来源:廖雪峰的官方网站,作者:廖雪峰. [一] 在Web系统中,用户登录是最基本的功能.要实现用户名+密码登录,很多同学的第一想法就是直接创建一个Users表,包含username和password两列,这样,就可以实现登录了: id | username | password | name等其他字段 ----+----------

如果系统要使用超大整数(超过long长度范围),请你设计一个数据结构来存储这种超大型数字以及设计一种算法来实现超大整数加法运算

package interview_10_10; import org.junit.Test; public class T1 { /** * 如果系统要使用超大整数(超过long长度范围),请你设计一个数据结构来存储这种超大型数字以及设计一种算法来实现超大整数加法运算). */ @Test public void test1() { String number1 = "4324328732789"; String number2 = "2383244324324325898