多线程下如何保证缓存一致性
缓存维护方案一假设有一写(线程A)一读(线程B)操作,先操作缓存,在操作数据库。,如下流程图所示:
1)线程A发起一个写操作,第一步del cache
2)线程A第二步写入新数据到DB
3)线程B发起一个读操作,cache miss,
4)线程B从DB获取最新数据
5)请求B同时set cache
这样看,没啥问题。我们再看第二个流程图,如下:
1)线程A发起一个写操作,第一步del cache
2)此时线程B发起一个读操作,cache miss
3)线程B继续读DB,读出来一个老数据
4)然后老数据入cache
5)线程A写入了最新的数据
OK,酱紫,就有问题了吧,老数据入到缓存了,每次读都是老数据啦,缓存与数据与数据库数据不一致。
缓存维护方案二双写操作,先操作缓存,在操作数据库。
1)线程A发起一个写操作,第一步set cache
2)线程A第二步写入新数据到DB
3)线程B发起一个写操作,set cache,
4)线程B第二步写入新数据到DB
这样看,也没啥问题。,但是有时候可能事与愿违,我们再看第二个流程图,如下:
1)线程A发起一个写操作,第一步set cache
2 ...
spring中多线程情况下如何保证事务
背景Springboot项目,有个需求,需要提供接口,接口调用方每一次调用时,会保存或者更新大量数据,接口需要满足以下要求:
数据保存要保证数据原子性:要么全部保存成功,要么全部不保存。
保证接口性能。
实践发现,即使使用批量保存,接口耗时也久,所以需要开启多线程来保存。现在的问题是,在开启多线程保存的情况下,如何保证数据的原子性。
使用声明式事务出现的问题具体代码如下:
123456789101112131415161718192021@Transactional(rollbackFor = Exception.class)public boolean saveUser() { Long userId = 1L; CompletableFuture<Void> f1 = CompletableFuture.runAsync(() -> { User user = new User(); user.setId(userId); ...
ClickHouse 中的常用聚合函数(十一)
ClickHouse 中的常用聚合函数(十一) 本文来源: ( https://www.cnblogs.com/traditional/tag/ClickHouse:一款速度快到让人发指的列式存储数据库/ )
楔子这次来说一下 ClickHouse 中的聚合函数,因为和关系型数据库的相似性,本来聚合函数不打算说的,但是 ClickHouse 提供了很多关系型数据库中没有的函数,所以我们还是从头了解一下。
count:计算数据的行数,有以下几种方式:
count(字段):计算该字段中不为 Null 的元素数量
count()、count(*):计算数据集的总行数
所有如果某个字段中不包含 Null,那么对该字段进行 count 得到的结果和 count()、count(*) 是相等的。
12345SELECT count(), count(*), count(product) FROM sales_data;/*┌─count()─┬─count()─┬─count(product)─┐│ 1349 │ 1349 │ ...
ClickHouse 中其它常见的表引擎(八)
ClickHouse 中其它常见的表引擎(八) 本文来源: ( https://www.cnblogs.com/traditional/tag/ClickHouse:一款速度快到让人发指的列式存储数据库/ )
楔子Everything is table(万物皆为表)是 ClickHouse 的一个非常有意思的设计思路,正因为 ClickHouse 是一款数据库,所以自然而然数据表就是它的武器,是它与外部进行交互的接口层。在数据表背后无论连接的是本地文件、HDFS、zookeeper,还是其它服务,终端用户只需要面对数据表,只需要使用 SQL 查询语言。
下面就来介绍一下其它类型的表引擎,它们以表为接口,极大地丰富了 ClickHouse 的查询能力。这些表引擎各自特点突出,或是独立地应用于特定场景,或是能够与 MergeTree 搭配使用。例如外部存储系列的表引擎,能够直接读取其它系统的数据,ClickHouse 自身只负责元数据的管理,类似使用外部表的形式;内存系列的表引擎,能够充当数据分发的临时存储载体或消息通道;日志文件系列的表引擎,拥有简单 ...
ClickHouse 中最重要的表引擎:MergeTree 的深度原理解析(六)
ClickHouse 中最重要的表引擎:MergeTree 的深度原理解析(六) 本文来源: ( https://www.cnblogs.com/traditional/tag/ClickHouse:一款速度快到让人发指的列式存储数据库/ )
楔子表引擎是 ClickHouse 中的一大特色,可以说表引擎决定了一张表最终的性格,比如数据表拥有何种特性、数据以何种形式被存储以及如何被加载。ClickHouse 拥有非常庞大的表引擎体系,总共有合并树、外部存储、内存、文件、接口和其它 6 大类 20 多种表引擎,而在这众多的表引擎中,又属合并树(MergeTree)表引擎及其家族系列(*MergeTree)最为强大,在生产环境中绝大部分场景都会使用此引擎。因为只有合并树系列的表引擎才支持主键索引、数据分区、数据副本、数据采样等特性,同时也只有此系列的表引擎支持 ALTER 相关操作。因此这里我们着重介绍合并树,因为它非常非常非常重要,并且难度也最高,至于其它的表引擎由于比较简单,所以我们放到后面再介绍。
当然我们说合并树家族自身也有很多表引擎的变种,其 ...
ClickHouse 其它的一些操作函数 (十五)
ClickHouse 其它的一些操作函数 (十五) 本文来源: ( https://www.cnblogs.com/traditional/tag/ClickHouse:一款速度快到让人发指的列式存储数据库/ )
楔子在 ClickHouse 中还存在一些其它比较有意思的函数,我们来看一下。
and:计算多个值逻辑与连接的结果
该函数只能接收 整型、浮点型和 Null,其逻辑和 Python 中的 and 类似
1234567891011121314SELECT and(1, 2, 0, Null, 3, 5);/*┌─and(1, 2, 0, NULL, 3, 5)─┐│ 0 │└──────────────────────────┘*/-- 等价于SELECT 1 AND 2 AND 0 AND Null AND 3 AND 5;/*┌─and(1, 2, 0, NULL, 3, 5)─┐│ 0 │└──────────────────────────┘ ...
ClickHouse 中的数据查询以及各种子句(九)
ClickHouse 中的数据查询以及各种子句(九) 本文来源: ( https://www.cnblogs.com/traditional/tag/ClickHouse:一款速度快到让人发指的列式存储数据库/ )
楔子作为一款 OLAP 型的数据库,它的查询功能可谓是重中之重,而且我相信大家在绝大部分时间都在使用它的查询功能,事实上,在日常运转的过程中,数据查询也是 ClickHouse 的主要工作之一。ClickHouse 完全使用 SQL 作为查询语言,能够以 SELECT 查询语句的形式从数据库中选取数据,这也是它具备流行潜质的重要原因。虽然 ClickHouse 拥有优秀的查询性能,但是我们也不能滥用查询,掌握 ClickHouse 所支持的各种查询子句,并选择合理的查询形式是很有必要的。使用不恰当的 SQL 语句进行查询不仅会带来低性能,还可能导致不可预知的系统错误。
虽然在上面的示例中,我们已经见识过一些查询语句的用法,但那些都是为了演示效果简化后的代码,与真正的生产环境中的代码相差较大。例如在绝大部分场景中,都应该避免使用 SELE ...
ClickHouse 之 MergeTree 家族中的其它表引擎(七)
ClickHouse 之 MergeTree 家族中的其它表引擎(七) 本文来源: ( https://www.cnblogs.com/traditional/tag/ClickHouse:一款速度快到让人发指的列式存储数据库/ )
目前在 ClickHouse 中,按照特点可以将表引擎分为 6 个系列,分别是合并树、外部存储、内存、文件、接口和其它,每一个系列的表引擎都有独自的特点和使用场景。而其中最核心的当属 MergeTree 系列,因为它们拥有最为强大的性能和最为广泛的使用场景。
经过之前的介绍,我们知道 MergeTree 有两种含义:
1. 表示合并树表引擎家族
2. 表示合并树表引擎家族中最基础的 MergeTree 表引擎
而在整个家族中,除了基础表引擎 MergeTree 之外,常用的表引擎还有 ReplacingMergeTree、SummingMergeTree、AggregatingMergeTree、CollapsingMergeTree、VersionedCollapsingMergeTree。从名字也能看出来,每一 ...
ClickHouse 字符串的相关操作函数(十二)
ClickHouse 字符串的相关操作函数(十二) 本文来源: ( https://www.cnblogs.com/traditional/tag/ClickHouse:一款速度快到让人发指的列式存储数据库/ )
楔子下面来说一说字符串的相关操作。
empty:检测一个字符串是否为空,为空返回 1,不为空返回 0
notEmpty:检测一个字符串是否不为空,不为空返回 1,为空返回 0
12345678910111213SELECT empty(''), empty('satori');/*┌─empty('')─┬─empty('satori')─┐│ 1 │ 0 │└───────────┴─────────────────┘*/SELECT notEmpty(''), notEmpty('satori');/*┌─notEmpty('')─┬─notEmpty( ...
ClickHouse 日期时间的相关操作函数(十三)
ClickHouse 日期时间的相关操作函数(十三) 本文来源: ( https://www.cnblogs.com/traditional/tag/ClickHouse:一款速度快到让人发指的列式存储数据库/ )
楔子下面来说一说日期和时间的相关操作。
toDate、toDateTime:将字符串转成 Date、DateTime
12345678910111213141516171819202122SELECT toDate('2020-11-11 12:12:12') v1, toDateTime('2020-11-11 12:12:12') v2;/*┌─────────v1─┬──────────────────v2─┐│ 2020-11-11 │ 2020-11-11 12:12:12 │└────────────┴─────────────────────┘*/-- 当然除了字符串,也可以传入 DateTime、DateWITH toDate('2020-11-11 12:12:12 ...