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版]

  1. 增删改查入门。快速展现用法,代码配置连接字符串
  2. 数据模型文件。建立表格字段和索引,名字以及数据类型规范,推荐字段(时间,用户,IP)
  3. 实体类详解。数据类业务类,泛型基类,接口
  4. 功能设置。连接字符串,调试开关,SQL日志,慢日志,参数化,执行超时。代码与配置文件设置,连接字符串局部设置
  5. 反向工程。自动建立数据库数据表
  6. 数据初始化。InitData写入初始化数据
  7. 高级增删改。重载拦截,自增字段,Valid验证,实体模型(时间,用户,IP)
  8. 脏数据。如何产生,怎么利用
  9. 增量累加。高并发统计
  10. 事务处理。单表和多表,不同连接,多种写法
  11. 扩展属性。多表关联,Map映射
  12. 高级查询。复杂条件,分页,自定义扩展FieldItem,查总记录数,查汇总统计
  13. 数据层缓存。Sql缓存,更新机制
  14. 实体缓存。全表整理缓存,更新机制
  15. 对象缓存。字典缓存,适用用户等数据较多场景。
  16. 百亿级性能。字段精炼,索引完备,合理查询,充分利用缓存
  17. 实体工厂。元数据,通用处理程序
  18. 角色权限。Membership
  19. 导入导出。Xml,Json,二进制,网络或文件
  20. 分表分库。常见拆分逻辑
  21. 高级统计。聚合统计,分组统计
  22. 批量写入。批量插入,批量Upsert,异步保存
  23. 实体队列。写入级缓存,提升性能。
  24. 备份同步。备份数据,恢复数据,同步数据
  25. 数据服务。提供RPC接口服务,远程执行查询,例如SQLite网络版
  26. 大数据分析。ETL抽取,调度计算处理,结果持久化

[NewLife.XCode]增量累加的更多相关文章

  1. [NewLife.XCode]对象字典缓存(百万军中取敌首级)

    NewLife.XCode是一个有10多年历史的开源数据中间件,支持nfx/netcore,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode. 整个系列教程会大量结合示例代码和 ...

  2. [NewLife.XCode]高级增删改

    NewLife.XCode是一个有10多年历史的开源数据中间件,支持nfx/netstandard,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode. 整个系列教程会大量结合示 ...

  3. [NewLife.XCode]实体列表缓存(最土的方法实现百万级性能)

    NewLife.XCode是一个有10多年历史的开源数据中间件,支持nfx/netcore,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode. 整个系列教程会大量结合示例代码和 ...

  4. [NewLife.XCode]增删改查入门

    NewLife.XCode是一个有10多年历史的开源数据中间件,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode. 整个系列教程会大量结合示例代码和运行日志来进行深入分析,蕴含 ...

  5. [NewLife.XCode]数据模型文件

    NewLife.XCode是一个有10多年历史的开源数据中间件,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode. 整个系列教程会大量结合示例代码和运行日志来进行深入分析,蕴含 ...

  6. [NewLife.XCode]实体类详解

    NewLife.XCode是一个有10多年历史的开源数据中间件,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode. 整个系列教程会大量结合示例代码和运行日志来进行深入分析,蕴含 ...

  7. [NewLife.XCode]功能设置

    NewLife.XCode是一个有10多年历史的开源数据中间件,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode. 整个系列教程会大量结合示例代码和运行日志来进行深入分析,蕴含 ...

  8. [NewLife.XCode]反向工程(自动建表建库大杀器)

    NewLife.XCode是一个有10多年历史的开源数据中间件,支持nfx/netstandard,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode. 整个系列教程会大量结合示 ...

  9. [NewLife.XCode]数据初始化

    NewLife.XCode是一个有10多年历史的开源数据中间件,支持nfx/netstandard,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode. 整个系列教程会大量结合示 ...

随机推荐

  1. redis学习-string常用命令

    keys * :查询所有的key值 set:为指定键设置对应的值 get:获取指定键的值 mset:一次传入多个键值对 mget:一次获取多个键的值 del:删除指定键 strlen:获取指定键值的长 ...

  2. 1034 Head of a Gang 图的遍历,map使用

    命名冲突,导致编译失败.这大概就是之前看到的最好不要using namespace std:的原因

  3. sftp修改用户home目录后登录时报connection closed by remote host

    在sftp用户需要修改登录根目录的情况下,我们可以修改/etc/ssh/sshd_config文件中ChrootDirectory /home/[path]的路径. 但是,在重启sshd服务后,sft ...

  4. 【翻译】从头开始写一个时间序列数据库-Writing a Time Series Database from Scratch

    本文来自: https://fabxc.org/tsdb/, 如翻译有误,请纠正. 我是从事监控工作的.特别是Prometheus, 一个包含自定义的时间序列库以及集成Kuberntes的监控系统. ...

  5. CSS3背景相关新增属性

    background-clip border-box:充满边框和内边距,内容. padding-box:充满内边距,内容 content-box:只充满内容 background-origin bor ...

  6. SpringBoot 基础01

    SpringBoot 基础 pom.xml <!-- Spring Boot 依赖版本控制 --> <parent> <groupId>org.springfram ...

  7. formated time string for file naming

    #include <stdio.h> #include <time.h> int main() { time_t rawtime; struct tm *timeinfo; ] ...

  8. POJ2391 Ombrophobic Bovines

    Ombrophobic Bovines Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 19359   Accepted: 4 ...

  9. sqoop错误集锦2

    1.使用sqoop技术将mysql的数据导入到Hive出现的错误如下所示: 第一次使用命令如下所示: 1 [hadoop@slaver1 sqoop-1.4.5-cdh5.3.6]$ bin/sqoo ...

  10. 使用PowerShell快速部署Win12R2虚拟化桌面

    PowerShell一直是微软windows_Server产品中重要的一部分,可以通过PowerShell来完成所有的服务器配置,甚至一些在图形界面下无法完成的事情.随着每一个新版本的微软产品或者服务 ...