[NewLife.XCode]增量累加
NewLife.XCode是一个有10多年历史的开源数据中间件,支持nfx/netstandard,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode。
整个系列教程会大量结合示例代码和运行日志来进行深入分析,蕴含多年开发经验于其中,代表作有百亿级大数据实时计算项目。
开源地址:https://github.com/NewLifeX/X(求star, 729+)
累加的需求背景
一个网站,部署了两台应用服务器,共用数据库,其中文章表有个访问次数的字段。
现在需要记录访问次数,需要怎么做?
var entity = Article.FindByID();
entity.Views++;
entity.Update();
如果两台服务器都有用户访问了9527这篇文章,访问前Views是1000,访问后是多少?1002?大部分情况下是1002,少数情况下可能是1001。
如果每台服务器都有100个用户同时访问这篇文章呢?那可就精彩了,最后访问数可能是1001到1200之间的某个数。
按照教科书做法,我们似乎应该开个事务加个锁,确保同时只能有一个用户(线程)修改这一行数据。
且不说加锁和事务成本有多高,光是为了一个字段就锁住这一行导致用户无法更新这一行其它字段,就让人觉得挺不地道的。再者,访问次数对于其它字段来说,也许并没有那么重要。
聪明如你,可以想到这么一个办法:
update article set views=views+1 where id=9527
哈,这就是XCode增量累加的出发点,每个用户(线程)执行自己的那一次,不管排队先后,最终结果都将会是1200。
设置增量累加
在实体类静态构造函数中,可以设置需要增量累加的字段
向 Meta.Factory.AdditionalFields 添加需要采用增量累加的字段,执行update时才生成 x=x+123 样子的语句。
测试代码:
Update VisitStat Set Times=Times+123,Users=Users+1,IPs=IPs+1,UpdateTime='2019-03-26 22:36:14' Where ID=1
从输出效果看到,产生了累加效果。并且,这段代码不管执行多少次,都是这样的累加效果,而不管实际值是多少。
累加原理
从数据库查出来一个对象时,如果发现有设置累加字段,XCode会把此时的数据“备份” 下来。
在执行update保存的时候,拿累加字段的最后值减去原始备份值,得到差值(可能是负数),生成 x=x+123 或 x=x-456 的语句。
不光整数,小数也可以设置累加字段。
需要注意的是,如果字段x允许空,并且要更新行的x字段刚好为NULL,x=x+123 将会得不到预期效果。
高级用法
再看开头的例子,即使使用了累加,不需要加锁以及开事务,仍然需要update数据库200次。
借助累加以及异步保存功能,可以把这个次数大大降低。
var entity = Article.FindByID(9527);
entity.Views++;
entity.SaveAsync(5_000);
先把Views设为累加字段。
Article.FindByID内部可以用对象缓存,然后每台应用服务器在10秒(默认缓存时间)内多线程查到的都是同一个entity对象。
SaveAsync将把对象entity放入实体队列,5秒后延迟保存。如果200用户访问集中在5秒内,最后每台服务器只会执行一次update操作。
Update Article Set Viewss=Views+100 Where ID=9527
数据库写入次数由200次下降到2次,提升100倍。
由此,你能想到什么更有意思的用法了吗?
系列教程
NewLife.XCode教程系列[2019版]
- 增删改查入门。快速展现用法,代码配置连接字符串
- 数据模型文件。建立表格字段和索引,名字以及数据类型规范,推荐字段(时间,用户,IP)
- 实体类详解。数据类业务类,泛型基类,接口
- 功能设置。连接字符串,调试开关,SQL日志,慢日志,参数化,执行超时。代码与配置文件设置,连接字符串局部设置
- 反向工程。自动建立数据库数据表
- 数据初始化。InitData写入初始化数据
- 高级增删改。重载拦截,自增字段,Valid验证,实体模型(时间,用户,IP)
- 脏数据。如何产生,怎么利用
- 增量累加。高并发统计
- 事务处理。单表和多表,不同连接,多种写法
- 扩展属性。多表关联,Map映射
- 高级查询。复杂条件,分页,自定义扩展FieldItem,查总记录数,查汇总统计
- 数据层缓存。Sql缓存,更新机制
- 实体缓存。全表整理缓存,更新机制
- 对象缓存。字典缓存,适用用户等数据较多场景。
- 百亿级性能。字段精炼,索引完备,合理查询,充分利用缓存
- 实体工厂。元数据,通用处理程序
- 角色权限。Membership
- 导入导出。Xml,Json,二进制,网络或文件
- 分表分库。常见拆分逻辑
- 高级统计。聚合统计,分组统计
- 批量写入。批量插入,批量Upsert,异步保存
- 实体队列。写入级缓存,提升性能。
- 备份同步。备份数据,恢复数据,同步数据
- 数据服务。提供RPC接口服务,远程执行查询,例如SQLite网络版
- 大数据分析。ETL抽取,调度计算处理,结果持久化
[NewLife.XCode]增量累加的更多相关文章
- [NewLife.XCode]对象字典缓存(百万军中取敌首级)
NewLife.XCode是一个有10多年历史的开源数据中间件,支持nfx/netcore,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode. 整个系列教程会大量结合示例代码和 ...
- [NewLife.XCode]高级增删改
NewLife.XCode是一个有10多年历史的开源数据中间件,支持nfx/netstandard,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode. 整个系列教程会大量结合示 ...
- [NewLife.XCode]实体列表缓存(最土的方法实现百万级性能)
NewLife.XCode是一个有10多年历史的开源数据中间件,支持nfx/netcore,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode. 整个系列教程会大量结合示例代码和 ...
- [NewLife.XCode]增删改查入门
NewLife.XCode是一个有10多年历史的开源数据中间件,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode. 整个系列教程会大量结合示例代码和运行日志来进行深入分析,蕴含 ...
- [NewLife.XCode]数据模型文件
NewLife.XCode是一个有10多年历史的开源数据中间件,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode. 整个系列教程会大量结合示例代码和运行日志来进行深入分析,蕴含 ...
- [NewLife.XCode]实体类详解
NewLife.XCode是一个有10多年历史的开源数据中间件,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode. 整个系列教程会大量结合示例代码和运行日志来进行深入分析,蕴含 ...
- [NewLife.XCode]功能设置
NewLife.XCode是一个有10多年历史的开源数据中间件,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode. 整个系列教程会大量结合示例代码和运行日志来进行深入分析,蕴含 ...
- [NewLife.XCode]反向工程(自动建表建库大杀器)
NewLife.XCode是一个有10多年历史的开源数据中间件,支持nfx/netstandard,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode. 整个系列教程会大量结合示 ...
- [NewLife.XCode]数据初始化
NewLife.XCode是一个有10多年历史的开源数据中间件,支持nfx/netstandard,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode. 整个系列教程会大量结合示 ...
随机推荐
- mysql中gbk_chinese_ci与gbk_bin区别
如果在query browser中选create new table在字符集的选择中collation栏有两个选择gbk_chinese_ci与gbk_bin gbk_bin是二进制存储.区分大小写的 ...
- P3805 【模板】manacher算法
#include <bits/stdc++.h> #define up(i,l,r) for(register int i = (l);i <= (r); i++) #define ...
- mpdf-html转PDF,中文字符乱码、加粗问题
$defaultConfig = (new ConfigVariables())->getDefaults(); $fontDirs = $defaultConfig['fontDir']; $ ...
- mysql 数据库链接 过期产品
注意下面的"@" 必须要加的!否则会报错! $link = @mysql_connect('localhost','root','root') or die("link ...
- Docker优势以及与传统虚拟机对比(1)
docker优势 1.更快速地交付和部署: 2.更高的虚拟化(不需要额外的hypervisor支持,是内核级的虚拟化,实现更高的性能呢和效率): 3.更轻松的迁移和扩展: 4.更简单的管理 与传统的 ...
- REdis Asynchronous AOF fsync is taking too long
redis.conf中的no-appendfsync-on-rewrite默认值为no,表示在重写AOF文件或RDB文件时阻塞fsync. 如果重写AOF或RDB文件时长过长,则在日志中可以看到如下信 ...
- Eclipse搭建服务器,实现与Android的简单通信
---恢复内容开始--- 目标:实现客户端(Android App)与服务器(PC)的简单通信 相关准备:eclipse_mars.tomcat8.Android Studio 实现: 1.java环 ...
- HTML基本格式和文本元素(标签)介绍
<!doctype html>//声明文档类型 <html lang="zh-cn">//文档开始,后面是声明是中文页面的意思,en是英语的意思 <h ...
- fiddler两种方式设置断点
第一种:打开Fiddler 点击Rules-> Automatic Breakpoint ->Before Requests(这种方法会中断所有的会话) 如何消除命令呢? 点击Rule ...
- 无知小子踏入python web大门
学习python flask的第一天,费劲我小白的脑子,总算完成了环境配置 详情如下,其他小白误走弯路,希望和我一样爱好python的人坚信:python或许是最好的语言! 那么,开始喽,有不对的地方 ...