- 博客(89)
- 收藏
- 关注
原创 【Go 基础】并发相关
首先,要明确并行和并发的概念。并行,是指两个或者多个事件在同一时刻发生。并发,是指两个或多个事件在同一时间间隔发生。并发偏重于多个任务交替执行,而多个任务之间还可能是串行的。而并行才是真正意义上的“同时执行”。**并发编程是指在一台机器上“同时”处理多个任务。**并发是在同一实体上的多个事件,多个事件在同一时间间隔发生。并发编程的目标是充分的利用处理器的每一个核,以达到最高的处理性能。
2024-12-08 20:57:54
263
原创 【Go 基础】channel
前者就是传统的加锁,后者就是 channel。也即,channel 的主要目的就是在多任务间传递数据的,本身就是安全的。
2024-12-02 19:59:56
314
1
原创 【实战篇】波动的响应延迟:如何应对变慢的Redis?
在 Redis 的实际部署应用中,有一个非常严重的问题,那就是 Redis 突然变慢了。一旦出现这个问题,不仅会直接影响用户的使用体验,还可能会影响到“旁人”,也就是和 Redis 在同一个业务系统中的其他系统,比如说数据库。
2024-11-22 18:32:11
1075
原创 【实践篇】为什么CPU结构也会影响Redis的性能?
CPU 的多核架构以及多 CPU 架构,也会影响到 Redis 的性能。如果不了解 CPU 对 Redis 的影响,在对 Redis 的性能进行调优时,就可能会遗漏一些调优方法,不能把 Redis 的性能发挥到极限。今天,我们就来学习下目前主流服务器的 CPU 架构,以及基于 CPU 多核架构和多 CPU 架构优化 Redis 性能的方法。
2024-11-22 18:31:57
1012
原创 【Go 开发】pprof 排查问题流程:排查程序 CPU 占用高的问题
这样会在 localhost:6060 启动一个 HTTP 服务器,可以在浏览器打开 http://localhost:6060/debug/pprof/ 查看各类 pprof 信息。常见的 pprof 分析命令进入 pprof 交互式命令行界面后,可以使用以下命令进行分析:• top:显示 CPU 或内存消耗最多的函数,默认按消耗排序。• list <function_name>:查看指定函数的源码以及性能消耗信息。• web:以图形界面展示性能分析结果(需要安装 Graphviz)。
2024-11-14 15:44:23
688
原创 【实践篇】异步机制:如何避免单线程模型的阻塞?
Redis 之所以被广泛应用,很重要的一个原因就是它支持高性能访问。也正因为这样,我们必须要重视所有可能影响 Redis 性能的因素(例如命令操作、系统配置、关键机制、硬件配置等),不仅要知道具体的机制,尽可能避免性能异常的情况出现,还要提前准备好应对异常的方案。
2024-11-14 15:43:53
898
原创 【实践篇】消息队列的考验:Redis有哪些解决方案?
现在的互联网应用基本上都是采用分布式系统架构进行设计的,而很多分布式系统必备的一个基础软件就是消息队列。消息队列要能支持组件通信消息的快速读写,而 Redis 本身支持数据的高速访问,正好可以满足消息队列的读写性能需求。不过,除了性能,消息队列还有其他的要求,所以,很多人都很关心一个问题:“Redis 适合做消息队列吗?
2024-11-04 19:57:19
597
原创 【实践篇】如何在Redis中保存时间序列数据?
这些与发生时间相关的一组数据,就是时间序列数据。这些数据的特点是没有严格的关系模型,记录的信息可以表示成键和值的关系(例如,一个设备 ID 对应一条记录),所以,并不需要专门用关系型数据库(例如 MySQL)来保存。而 Redis 的键值数据模型,正好可以满足这里的数据存取需求。Redis 基于自身数据结构以及扩展模块,提供了两种解决方案。
2024-10-26 16:19:23
830
原创 【实战篇】GEO是什么?还可以定义新的数据类型吗?
为了实现自定义数据类型,首先,我们需要了解 Redis 的基本对象结构 RedisObject,因为 Redis 键值对中的每一个值都是用 RedisObject 保存的。RedisObject 包括元数据和指针。其中,元数据的一个功能就是用来区分不同的数据类型,指针用来指向具体的数据类型的值。所以,要想开发新数据类型,我们就先来了解下 RedisObject 的元数据和指针。
2024-10-26 16:19:02
1093
原创 【实践篇】有一亿个keys要统计,应该用哪种集合?
我们经常需要保存这样一种信息:一个 key 对应了一个数据集合。我们知道,Redis 集合类型的特点就是一个键对应一系列的数据,所以非常适合用来存取这些数据。但是,在这些场景中,除了记录信息,我们往往还需要对集合中的数据进行统计。通常情况下,我们面临的用户数量以及访问量都是巨大的,比如百万、千万级别的用户数量,或者千万级别、甚至亿级别的访问信息。所以,我们必须要选择能够非常高效地统计大量数据(例如亿级)的集合类型。:聚合统计、排序统计、二值状态统计和基数统计。
2024-10-17 16:29:54
963
原创 【基础篇】切片集群:数据增多了,是该加内存还是加实例?
当需要保存大量的数据的时候,可以选择大内存的主机来部署 Redis。但是在存储大量数据之后,Redis 的响应有时会非常慢。比如说,一台 32G 内存的机器,保存 25G 数据之后。使用 INFO 命令查看 Redis 的 latest_fork_usec 指标值(表示最近一次 fork 的耗时),结果显示这个指标值特别高,快到秒级别了。这跟 Redis 的持久化机制有关系。
2024-10-17 14:23:25
682
原创 【基础篇】哨兵集群:哨兵挂了,主从库还能切换吗?
上篇文章,我们学习了哨兵机制,它可以实现主从库的自动切换。通过部署多个实例,就形成了一个哨兵集群。哨兵集群中的多个实例共同判断,可以降低对主库下线的误判率。但是,我们还是要考虑一个问题:如果有哨兵实例在运行时发生了故障,主从库还能正常切换吗?实际上,一旦多个实例组成了哨兵集群,即使有哨兵实例出现故障挂掉了,其他哨兵还能继续协作完成主从库切换的工作,包括判定主库是不是处于下线状态,选择新主库,以及通知从库和客户端。
2024-10-15 17:50:00
1015
原创 【基础篇】哨兵机制:主库挂了,如何不间断服务?
上篇文章中,我们学习了主从库集群模式。在这个模式下,如果从库发生故障了,客户端可以继续向主库或其他从库发送请求,进行相关的操作,但是如果主库发生故障了,那就直接会影响到从库的同步,因为从库没有相应的主库可以进行数据复制操作了。而且,如果客户端发送的都是读操作请求,那还可以由从库继续提供服务,这在纯读的业务场景下还能被接受。但是,一旦有写操作请求了,按照主从库模式下的读写分离要求,需要由主库来完成写操作。此时,也没有实例可以来服务客户端的写操作请求了。
2024-10-15 17:49:32
882
原创 【基础篇】数据同步:主从库如何实现数据一致?
前两篇文章,我们学习了 AOF 和 RDB,如果 Redis 发生了宕机,它们可以分别通过回放日志和重新读入 RDB 文件的方式恢复数据,从而保证尽量少丢失数据,提升可靠性。不过,即使用了这两种方法,也依然存在服务不可用的问题。比如说,我们在实际使用时只运行了一个 Redis 实例,那么,如果这个实例宕机了,它在恢复期间,是无法服务新来的数据存取请求的。那我们总说的 Redis 具有高可靠性,又是什么意思呢?。AOF 和 RDB 保证了前者,而对于后者,Redis 的做法就是。
2024-10-15 17:49:08
1042
原创 【基础篇】内存快照:宕机后,Redis如何实现快速恢复?
之前,我们学习了 Redis 避免数据丢失的 AOF 方法。这个方法的好处,是每次执行只需要记录操作命令,需要持久化的数据量不大。一般而言,只要你采用的不是 always 的持久化策略,就不会对性能造成太大影响。但是,也正因为记录的是操作命令,而不是实际的数据,所以,用 AOF 方法进行故障恢复的时候,需要逐一把操作日志都执行一遍。如果操作日志非常多,Redis 就会恢复得很缓慢,影响到正常使用。这当然不是理想的结果。那么,还有没有既可以保证可靠性,还能在宕机时实现快速恢复的其他方法呢?
2024-10-14 10:00:36
1080
原创 【基础篇】AOF日志:宕机了,Redis如何避免数据丢失?
如果有人问你:“你会把 Redis 用在什么业务场景下?”我想你大概率会说:“我会把它当作缓存使用,因为它把后端数据库中的数据存储在内存中,然后直接从内存中读取数据,响应速度会非常快。我们很容易想到的一个解决方案是,从后端数据库恢复这些数据,但这种方式存在两个问题:一是,需要频繁访问数据库,会给数据库带来巨大的压力;二是,这些数据是从慢速数据库中读取出来的,性能肯定比不上从 Redis 中读取,导致使用这些数据的应用程序响应变慢。
2024-10-14 10:00:12
2452
原创 【基础篇】高性能IO模型:为什么单线程Redis能那么快?
今天,我们来探讨一个很多人都很关心的问题:“为什么单线程的 Redis 能那么快?首先,先厘清一个事实,我们通常说,Redis 是单线程,主要是指但 Redis 的其他功能,比如持久化、异步删除、集群数据同步等,其实是由额外的线程执行的。所以,严格来说,Redis 并不是单线程,但是我们一般把 Redis 称为单线程高性能,这样显得“酷”些。
2024-10-12 10:27:31
655
原创 【基础篇】数据结构:快速的Redis有哪些慢操作?
数据库这么多,为啥 Redis 能有这么突出的表现呢?一方面,这是因为它是内存数据库,所有操作都在内存上完成,内存的访问速度本身就很快。另一方面,这要归功于它的数据结构。简单来说,底层数据结构一共有 6 种,分别是简单动态字符串、双向链表、压缩列表、哈希表、跳表和整数数组。它们和数据类型的对应关系如下图所示:可以看到,String 类型的底层实现只有一种数据结构,也就是简单动态字符串。而 List、Hash、Set 和 Sorted Set 这四种数据类型,都有两种底层实现结构。
2024-10-12 10:27:05
635
原创 【基础篇】一个键值数据库包含什么?
今天,在构造这个简单的键值数据库时,我们只需要关注整体架构和核心模块。这就相当于医学上在正式解剖人体之前,会先解剖一只小白鼠。我们通过剖析这个最简单的键值数据库,来迅速抓住学习和调优 Redis 的关键。我们把这个简单的键值数据库称为 SimpleKV。需要注意的是,GitHub 上也有一个名为 SimpleKV 的项目,这跟我说的 SimpleKV 不是一回事,我说的只是一个具有关键组件的键值数据库架构。
2024-10-08 18:05:02
1009
原创 【实战篇】自增id用完怎么办?
说到自增 id,第一个想到的应该就是表结构定义里的自增字段,也就是我们之前介绍过的自增主键 id。表定义的自增值达到上限后的逻辑是:再申请下一个 id 时,得到的值保持不变。//成功插入一行 4294967295*/可以看到,第一个 insert 语句插入数据成功后,这个表的 AUTO_INCREMENT 没有改变(还是 4294967295),就导致了第二个 insert 语句又拿到相同的自增 id 值,再试图执行插入语句,报主键冲突错误。
2024-09-29 11:50:31
1124
原创 【实战篇】要不要使用分区表?
我在表 t 中初始化插入了两行记录,按照定义的分区规则,这两行记录分别落在 p_2018 和 p_2019 这两个分区上。可以看到,这个表包含了一个.frm 文件和 4 个.ibd 文件,每个分区对应一个.ibd 文件。
2024-09-29 11:50:10
806
原创 【实战篇】grant之后要跟着flush privileges吗?
在 MySQL 里面,grant 语句是用来给用户赋权的。不知道你有没有见过一些操作文档里面提到,grant 之后要马上跟着执行一个 flush privileges 命令,才能使赋权语句生效。那么,grant 之后真的需要执行 flush privileges 吗?如果没有执行这个 flush 命令的话,赋权语句真的不能生效吗?接下来,我就先和你介绍一下 grant 语句和 flush privileges 语句分别做了什么事情,然后再一起来分析这个问题。
2024-09-29 11:49:45
648
原创 【实战篇】怎么最快地复制一张表?
怎么在两张表中拷贝数据?如果可以控制对源表的扫描行数和加锁范围很小的话,我们简单地使用 insert … select 语句即可实现。当然,为了避免对源表加读锁,更稳妥的方案是先将数据写到外部文本文件,然后再写回目标表。这时,有两种常用的方法。接下来的内容,我会和你详细展开一下这两种方法。假设,我们要把 db1.t 里面 a>900 的数据行导出来,插入到 db2.t 中。
2024-09-29 11:49:18
835
原创 【实战篇】insert语句的锁为什么这么多?
在上一篇文章中,我们知道 MySQL 对自增主键锁做了优化,尽量在申请到自增 id 以后,就释放自增锁。因此,insert 语句是一个很轻量的操作。不过,这个结论对于“普通的 insert 语句”才有效。也就是说,还有些 insert 语句是属于“特殊情况”的,在执行过程中需要给其他资源加锁,或者无法在申请到自增 id 以后就立马释放自增锁。那么,今天这篇文章,我们就一起来聊聊这个话题。
2024-09-29 11:17:33
1111
原创 【实战篇】自增主键为什么不是连续的?
由于自增主键可以让主键索引尽量地保持递增顺序插入,避免了页分裂,因此索引更紧凑。之前我见过有的业务设计依赖于自增主键的连续性,也就是说,这个设计假设自增主键是连续的。但实际上,这样的假设是错的,因为自增主键不能保证连续递增。今天这篇文章,我们就来说说这个问题,看看什么情况下自增主键会出现 “空洞”?自增值保存在哪儿?在这个空表 t 里面执行 insert into t values(null, 1, 1); 插入一行数据,再执行 show create table 命令,就可以看到如下图所示的结果:
2024-09-29 11:13:46
781
1
原创 【实战篇】都说InnoDB好,那还要不要使用Memory引擎?
上一篇文章中,调整内部临时表大小前后的两个 group by 语句都用了 order by null,为什么使用内存临时表得到的语句结果里,0 这个值在最后一行;而使用磁盘临时表得到的结果里,0 这个值在第一行?今天我们就来看看,出现这个问题的原因吧。
2024-09-27 10:27:04
714
原创 【实战篇】什么时候会使用内部临时表?
之前我们介绍了 sort buffer、内部临时表和 join buffer。这三个数据结构都是用来存放语句执行过程中的中间数据,以辅助 SQL 语句的执行的。其中,我们在排序的时候用到了 sort buffer,在使用 join 语句的时候用到了 join buffer。然后,你可能会有这样的疑问,MySQL 什么时候会使用内部临时表呢?
2024-09-27 10:23:26
624
原创 【实战篇】为什么临时表可以重名?
在上一篇文章中,我们在优化 join 查询的时候使用到了临时表。为什么要用临时表呢?直接用普通表是不是也可以呢?今天我们就从这个问题说起:临时表有哪些特征,为什么它适合这个场景?这里,我需要先帮你厘清一个容易误解的问题:有的人可能会认为,临时表就是内存表。
2024-09-27 10:21:34
991
原创 【实战篇】join语句怎么优化?
在上一篇文章中,我们介绍了 join 语句的两种算法,分别是 Index Nested-Loop Join(NLJ) 和 Block Nested-Loop Join(BNL)。我们发现在使用 NLJ 算法的时候,其实效果还是不错的,比通过应用层拆分成多个语句然后再拼接查询结果更方便,而且性能也不会差。但是,BNL 算法在大表 join 的时候性能就差多了,比较次数等于两个表参与 join 的行数的乘积,很消耗 CPU 资源。当然了,这两个算法都还有继续优化的空间,我们今天就来聊聊这个话题。
2024-09-26 10:54:06
870
原创 【实战篇】到底可不可以使用join?
今天这篇文章,我们先来说说 join 语句到底是怎么执行的,然后再来回答这两个问题。为了便于量化分析,我还是创建两个表 t1 和 t2 来和说明。可以看到,这两个表都有一个主键索引 id 和一个索引 a,字段 b 上无索引。存储过程 idata() 往表 t2 里插入了 1000 行数据,在表 t1 里插入的是 100 行数据。
2024-09-26 10:53:32
1141
原创 【实战篇】我查这么多数据,会不会把数据库内存打爆?
我们考虑一个问题:我的主机内存只有 100G,现在要对一个 200G 的大表做全表扫描,会不会把数据库主机的内存用光了?这个问题确实值得担心,被系统 OOM(out of memory)可不是闹着玩的。但是,反过来想想,逻辑备份的时候,可不就是做整库扫描吗?如果这样就会把内存吃光,逻辑备份不是早就挂了?所以说,对大表做全表扫描,看来应该是没问题的。但是,这个流程到底是怎么样的呢?
2024-09-25 16:17:19
1911
原创 【实战篇】为什么还有kill不掉的语句?
在 MySQL 中有两个 kill 命令:一个是 kill query + 线程 id,表示终止这个线程中正在执行的语句;一个是 kill connection + 线程 id,这里 connection 可缺省,表示断开这个线程的连接,当然如果这个线程有语句正在执行,也是要先停止正在执行的语句的。不知道你在使用 MySQL 的时候,有没有遇到过这样的现象:使用了 kill 命令,却没能断开这个连接。再执行 show processlist 命令,看到这条语句的 Command 列显示的是 Killed。
2024-09-25 10:38:39
1236
原创 【实战篇】如何判断一个数据库是不是出问题了
我们之前了解了主备切换流程。在一主一备的双 M 架构里,主备切换只需要把客户端流量切到备库;而在一主多从架构里,主备切换除了要把客户端流量切到备库外,还需要把从库接到新主库上。主备切换有两种场景,一种是主动切换,一种是被动切换。而其中被动切换,往往是因为主库出问题了,由 HA 系统发起的。这也就引出了我们今天要讨论的问题:怎么判断一个主库出问题了?
2024-09-24 14:55:35
806
原创 【实战篇】读写分离有哪些坑?
上篇文章,我们讨论了一主多从架构。它的一个主要的应用场景就是:读写分离。我们今天继续讨论下,读写分离的一些问题。读写分离的主要目标就是分摊主库的压力。图 1 中的结构是客户端(client)主动做负载均衡,这种模式下一般会把数据库的连接信息放在客户端的连接层。也就是说,由客户端来选择后端数据库进行查询。还有一种架构是,在 MySQL 和客户端之间有一个中间代理层 proxy,客户端只连接 proxy, 由 proxy 根据请求类型和上下文决定请求的分发路由。
2024-09-23 18:04:20
903
原创 【实战篇】备库为什么会延迟好几个小时?
在上一篇文章中,我们介绍了几种可能导致备库延迟的原因。你会发现,这些场景里,不论是偶发性的查询压力,还是备份,对备库延迟的影响一般是分钟级的,而且在备库恢复正常以后都能够追上来。但是,如果备库执行日志的速度持续低于主库生成日志的速度,那这个延迟就有可能成了小时级别。而且对于一个压力持续比较高的主库来说,备库很可能永远都追不上主库的节奏。这就涉及到今天要介绍的话题:备库并行复制能力。谈到主备的并行复制能力,我们要关注的是图中黑色的两个箭头。
2024-09-23 17:23:49
1141
原创 【实战篇】主库出问题了,从库怎么办?
之前我们介绍了MySQL主备复制的基础结构,但这些都是一主一备的结构。大多数的互联网应用场景都是读多写少,因此业务在发展过程中很可能先会遇到读性能的问题。而在数据库层解决读性能问题,就要涉及到接下来两篇文章要讨论的架构:一主多从。今天这篇文章,我们就先聊聊一主多从的切换正确性。然后,我们在下一篇文章中再聊聊解决一主多从的查询逻辑正确性的方法。图中,虚线箭头表示的是主备关系,也就是A和A’互为主备, 从库B、C、D指向的是主库A。
2024-09-23 17:23:32
895
原创 【实战篇】MySQL是怎么保证高可用的?
在一个主备关系中,每个备库接收主库的 binlog 并执行。正常情况下,只要主库执行更新生成的所有 binlog,都可以传到备库并被正确地执行,备库就能达到跟主库一致的状态,这就是最终一致性。但是,MySQL 要提供高可用能力,只有最终一致性是不够的。主备切换可能是一个主动运维动作,比如软件升级、主库所在机器按计划下线等,也可能是被动操作,比如主库所在机器掉电。我们先说明一个概念,即“同步延迟”。所谓主备延迟,就是同一个事务,在备库执行完成的时间和主库执行完成的时间之间的差值,也就是 T3-T1。
2024-09-20 11:57:13
1233
原创 【实战篇】MySQL是怎么保证主备一致的?
如图 1 所示就是基本的主备切换流程。在状态 1 中,客户端的读写都直接访问节点 A,而节点 B 是 A 的备库,只是将 A 的更新都同步过来,到本地执行。这样可以保持节点 B 和 A 的数据是相同的。当需要切换的时候,就切成状态 2。这时候客户端读写访问的都是节点 B,而节点 A 是 B 的备库。
2024-09-20 11:56:47
2453
3
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人