自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(115)
  • 收藏
  • 关注

原创 Redis主从、哨兵、cluster集群的部署和细节

哨兵架构下client端第一次从哨兵找出redis的主节点,后续就直接访问redis的主节点,不会每次都通过 sentinel代理访问redis的主节点,当redis的主节点发生变化,哨兵会第一时间感知到,并且将新的redis 主节点通知给client端(这里面redis的client端一般都实现了订阅功能,订阅sentinel发布的节点变动消息)当节点删除或者发生宕机时,节点上保存的数据也就丢失,但如果数据绑定的是插槽,那么当出现该情况时候,就可以将故障接的插槽转移到存活节点上。

2024-05-23 10:41:33 512

原创 Redis如何避免数据丢失?——RDB

写时复制的核心思想是 若有多个调用者同时请求相同资源,他们会共同获取相同的指针指向相同的资源,直到某个调用者视图修改资源的内容是,系统才会真正复制一个专用副本给该调用者,而其他调用者所见的最初的资源仍然保持不变,而该过程对其他的调用折是透明的,不被感知的。此作法主要的优点是如果调用者没有修改该资源,就不会有副本(private copy)被建立,因此多个调用者只是读取操作时可以共享同一份资源。

2024-05-10 15:00:12 1089

原创 Redis如何避免数据丢失?——AOF

Redis是把数据储存在内存的键值数据库,而服务器一旦宕机,那内存中的数据将全部丢失。像MySQL那样,是有宕机后数据恢复机制的。那Redis也是有的,其有两种方式:AOF和RDB。该章节讲解AOF。MySQL是使用redo log(重做日志)来进行宕机恢复的。其是使用了写前日志(Write Ahead Log,WAL),即是在实际写数据前,先把修改的数据写到日志文件中,方便出故障时候进行恢复。而AOF正好相反,是。这是个文本日志,不是二进制文件。

2024-05-08 11:10:14 899

原创 Redis的事务机制能保证ACID属性吗?

Redis使用 multi、exec、discard、watch 四个命令来支持事务机制。multi:开启一个事务exec:提交事务,从命令队列中取出提交的操作命令,进行实际执行discard: 放弃一个事务,清空命令队列watch:检测一个或多个键的值在事务执行过程中是否发生变化,若发生变化,当前事务就放弃执行Redis的事务机制可以保证一致性和隔离性和一定程度的原子性(不提供回滚),无法保证持久性。

2024-04-30 17:17:43 1216 1

原创 如何保证Redis双写一致性?

1.场景一:并发读写情况下产生的短暂不一致场景,业务场景要能接受。并发读写情况下,缓存正好失效且读操作耗时大于写操作而产生的数据不一致。可以通过延时删除,或者给redis设置较短的存活时间。

2024-04-29 14:27:26 1275

原创 Redis网络部分相关的结构体2 和 绑定回调函数细节

创建连接时候,需要设置客户端的读回调。createClient--->connSetReadHandler--->(conn->type->set_read_handler)--->(connSocketReadHandler,其内部把读回调函数readQueryFromClient赋值给read_handler)--->(aeCreateFileEvent,把conn->type->ae_handler赋值给rfileProc)。

2024-04-25 17:18:45 1036

原创 Redis网络相关的结构体 和 reactor模式

上一章节讲解了Redis的网络交互流程,没有对关于网络部分的结构体有具体的讲解,所以该文章就主要讲解Redis网络部分使用的结构体。

2024-04-25 10:10:48 924 1

原创 Redis网络模型

我们知道redis 是单线程的,但是严格意义来说,redis 的网络读取命令和解析、发送客户端数据是多线程的。

2024-04-24 10:47:00 934

原创 Redis是如何淘汰key的 -- 内存策略

Redis之所以性能强,最主要的原因是其是基于的(内存本身就是很快的)。然而。当内存使用达到上限的时候,Redis就无法存储更多数据了。那么,Redis是如何避免达到内存上限的,即是其内存策略是怎样的呢。

2024-04-21 13:19:31 659

原创 Redis对外可见的5种数据结构

所以,hash采用的编码与zset也基本一致的,只需把排序相关的skiplist去掉即可。通过封装, 可以根据对象的类型动态地选择存储结构和可以使用的命令, 实现节省空间和优化查询速度。Redis中会根据存储的数据类型不同,会选择不同的编码方式。根据存储的数据类型的不同,Redis会选择不同的编码方式,共包含11中不同类型。set是Redis中的集合,不保证元素有序的,其元素唯一,查询效率高。,dict和skiplist的优势不明显,而且会更耗内存。zset结构的编码转换是在插入时候进行判断的,在函数。

2024-04-18 10:30:20 937

原创 压缩列表的替代-----listpack

对比ziplist,listpack牺牲了内存使用率,从而避免了连锁更新的情况。而从代码复杂度上看,listpack也相对简单不少,也把增删改统一做出来,从其代码实现上看,是简洁高效的。listpack是在Redis5中就引入的(使用在streams),直到6才作为t_hash的御用底层数据结构。可以看出,极致的内存使用远远比不上Redis的处理性能。而且现在的内存价格是降低的,大容量内存的成本也没这么高。

2024-04-16 14:57:42 1072

原创 跳表skiplist

跳表可以说是平衡树的一种替代品。它也是为了解决的的问题。那这个问题,hash 表解决的很好,插入和查找都是 O(1) 的时间复杂度。但若呢?这个时候 hash 表就不行了,二叉查找树可以解决这个问题。但是由于二叉查找树在按大小顺序进行插入的时候,就会退化为链表。所以又出现了平衡二叉树,而根据算法不同,又分为AVL树、B-Tree、B+Tree、红黑树等。(先不用管这些数据结构的实现,其是复杂的)。而跳表的出现就是为了解决平衡二叉树复杂的问题,它以一种。

2024-04-12 15:25:04 759

原创 快速列表quicklist

和压缩列表一样,entry结构在储存时是一连串的内存块,需要将其每个entry节点的信息读取到管理该信息的结构体中,以便操作。便于在链表的两端进行插入和删除操作,在插入节点上复杂度很低,但是它的内存开销比较大,每个节点除了要保存数据之外,还要。quicklist是个双端链表,节点结构是quicklistNode,节点的zl字段指向压缩列表。​在 Redis 的早期设计中,如果列表类型的对象中元素的长度较小或数量比较少的,就采用。在Redis的quicklist结构中,实现了自己的迭代器,用于遍历节点。

2024-04-11 14:58:42 1045

原创 压缩列表ziplist

ziplist和普通的双向链表不同 ,ziplist不存储指向上一个链表节点和指向下一个链表节点的指针,而是存储上一个节点长度和当前节点长度,通过牺牲部分读写性能,来换取高效的内存空间利用率,节约内存,是一种时间换空间的思想。ziplist使用连续内存地址+偏移量的方式实现链表。适合存储一些int类型的数据或者长度比较短的字符串。压缩列表是 Redis 为节约空间而实现的一系列特殊编码的连续内存块组成的顺序型数据结构, 本质上是字节数组。

2024-04-10 14:13:05 711

原创 Go语言实现Redis分布式锁2

注意,这里也是使用Lua脚本封装了确认锁与锁续期的操作来用于原子化,以防止误续期了其他持有者的锁。这里仍然存在一个问题:当锁的持有者任务未完成,但是锁的有效期已过,虽然持有者此时仍可以完成任务,并且也不会误删其他持有者的锁,但是此时可能会存在多个执行者同时执行临界区代码,使得数据的一致性难以保证,造成意外的后果,分布式锁就失去了意义。因此,需要一个锁的自动续期机制,分布式锁框架Redission中就有这么一个看门狗,专门为将要到期的锁进行续期。之前的是只尝试获取一次锁,要是获取失败就不再尝试了。

2024-04-08 09:01:43 813 1

原创 整数集合intset

综上,Intset可以看做是特殊的整数数组Redis会确保lntset中的元素唯一、有序具备类型升级机制,可以节省内存空间底层采用二分查找方式来查询。

2024-04-08 08:54:40 741

原创 哈希字典Dict

在进行 rehash 期间,每次对字典执行 增、删、改、查操作时,程序除了执行指定的操作外,还会将 哈希表 ht[0].table中下标为 rehashidx 位置上的所有的键值对 全部迁移到 ht[1].table 上,完成后 rehashidx 自增。其实没有想象中的那么复杂,随着字典操作的不断执行,哈希表保存的键值对会不断增多(或者减少),为了让哈希表的负载因子维持在一个合理的范围之内,当哈希表保存的键值对数量太多或者太少时,需要对哈希表大小进行扩展或者收缩。,数组的每个元素称为一个哈希桶。

2024-04-07 15:50:41 701

原创 Go语言实现Redis分布式锁

本文将基于go语言,使用了一个常用的go Redis客户端一步一步探索与实现一个简单的Redis分布式锁。SETNX 命令用于在Redis中设置某个不存在的键的值。如果该键不存在,则设置成功,如果该键存在,则设置失败,不作任何动作。基于此可以实现一种简单的抢占机制。先连接redis。新建lock.go文件。创建lock结构体,加锁和解锁方法。

2024-04-04 16:09:43 1065 1

原创 redis链表结构和简单动态字符串(SDS)

这些看宏名字就很容易知道其功能的。//sds.h关于sdshdr##T,不太懂,在这里理解成它将sdshdr和T连接在一起,即表示不同的 sdshdr 类型。关于, 参数 s 是sdshdr 结构体中的字符串指针,即等价于 buf,参数 T 则是表示不同类型的 sdshdr,取值可以为 8/16/32/64。然后看其实现,是宏定义的一个变量,void*是将结果转换为void*类型,以便sh接收。而 (s) - ( sizeof(struct sdshdr##T) )则表示指向结构体变量的地址。

2024-04-02 09:14:11 670

原创 MySQL使用自增id无法插入id为0值的记录?

的时候,数据库会自动产生一个新的自增序列作为这条记录的ID。这就是我们插入0值ID记录时与期望不符原因。id是自增的,插入id=0的行数据,查看却显示id=10,这说明。因为在数据库表中ID采用了自增ID策略。这里就是记录下这种情况,该文章参考来自。这个情况有官方解释以及解决方案。

2024-03-21 14:27:17 214

原创 MySQL日志的一些疑惑解答

这时并不会回滚事务,虽然redo log是处于prepare阶段,但是能通过redolog的数据找到对应的binlog日志,这就是对应q情况2(a),MySQL认为对应的事务binlog是完整的,就会提交事务恢复数据。这个其实是不一定的。写了redolog后,会更新内存中的数据,要是这时进行查询,而数据还在内存中,就直接访问内存即可,不需要去读取磁盘,也不需要把redo log里的数据更新到数据磁盘中。在奔溃恢复时候,会对比磁盘数据页的LSN和checkpoint的LSN,要是其是相等的,就会跳过该页。

2024-03-20 10:44:30 865

原创 MySQL的日志:undo log、redo log、binlog有什么作用

在一个事务中执行下面语句。之后可能会对其有些疑惑:1.假如我想后撤,退回到update之前,而innodb是支持事务回滚的,即是可以有后悔药吃的,那是如何实现的呢?2.MySQL的行数据是存储在数据页中的(默认大小是16k)。该update语句需要操作的数据可能分布在多个数据页中,这样就需要对磁盘进行多处读写(即是随机读写),这样 IO 成本、查找成本都很高(随机读写比顺序读写慢很多)。而MySQL的速度却是比较快的,这和我们分析的不一致,这内部是使用了什么办法解决的呢?

2024-03-19 14:58:15 964

原创 MySQL的事务隔离是如何实现的?

事务是在 MySQL 引擎层实现的,默认的 InnoDB 引擎支持事务。MySQL InnoDB 引擎的默认隔离级别是可重复读(RR),但不建议将隔离级别升级为串行化,因为这会导致数据库并发时性能很差。针对快照读(普通 select 语句),是通过 MVCC 方式解决了幻读,因为可重复读隔离级别下,事务执行过程中看到的数据,一直跟这个事务启动时看到的数据是一致的,即使中途有其他事务插入了一条数据,是查询不出来这条数据的,所以就很好了避免幻读问题。针对当前读。

2024-03-13 15:41:53 1167

原创 MySQL的锁

锁是计算机协调多个进程或线程并发访问某一资源的机制。在 MySQL 里,根据加锁的范围,可以分为三类。

2024-03-12 11:20:28 918

原创 MySQL的加锁规则

加锁的规则:一个原则:加锁的基本单位是 next-key lock。加锁是对索引加锁的。一个bug:非唯一索引范围查询,该索引的临键锁不会有退化为间隙锁或记录锁。其他就通过常理来分析推理即可。唯一索引等值查询唯一索引范围查询非唯一索引等值查询非唯一索引范围查询非索引查询。

2024-03-11 16:53:49 1102

原创 Go实现日志2——支持结构化和hook

重点就是在e.fromat()和e.write()中。而在e.fromat()中按照规定的格式化数据后,把信息存在e.Buffer中,然后经由e.write()写入。其中日志记录的事件以结构化格式(键值对,或通常是 JSON)表示,随后可以通过编程方式对其进行解析,便于对日志进行监控、警报、审计等其他形式的分析。就不单单是输出msg=...。新的Format方法也好理解,主要是增添了调用appendKeyValue方法,该方法是进行键值对书写的。而JSON类型的是已经结构化,重点来看看TEXT文本格式的。

2024-03-05 16:54:19 818 2

原创 MySQL中有事务无法回滚的语句?

前面的修改表结构就是DDL语句。备注:若不了解DDL,可以查看该文章MySQL的SQL语句所有的 DDL 语句都会导致事务隐式提交。即是当你在执行 DDL 语句前,事务就已经提交了。这就意味着带有 DDL 语句的事务将来没有办法 rollback。看例子:在第5步查看结果的时候,发现表和插入的数据都有了,说明回滚没有生效。原因是在第3步,执行DDL语句之前事务就被隐式提交。DDL语句会进行隐式提交,是不能rollback的,所以大家在日常开发中一定要注意。

2024-03-04 18:08:06 751

原创 MySQL的一行数据是如何存储的?

1大多数人使用mysqly一般都是使用 InnoDB 引擎,这也是默认的表引擎。我们这里讨论的也是默认引擎InnoDB。InnoDB引擎表是数据是存储在磁盘的。那可能会好奇表的每一行是如何存储在磁盘中的呢?行结构是如何的呢?行格式(row_format),就是一条记录的存储结构。InnoDB 提供了 4 种行格式,分别是 Redundant、Compact、Dynamic和 Compressed 行格式。MySQL5.7 版本之后,默认使用 Dynamic 行格式。

2024-03-03 14:13:32 930

原创 Go实现日志

那接着来看日志选项,一个日志中会有很多选项,比如输出地方,输出格式,日志等级,是否输出行号等等。在输出中,也要输出日志等级,那肯定不是输出数字的,那是要输出例如"DEBUG"这种的,所以用map来映射。提供了initOptions函数来初始化日志选项,参数是传入函数。这里还没有实现logger结构体,所以还没有到使用设置的地方,讲到logger结构体的时候会再讲解。在日志输出时候,是会判别该日志等级是否符合设定的等级,就需要比较,所以日志类型就用数值类型就好。那首先是会有日志等级,一共6个等级。

2024-03-02 18:24:28 1159

原创 MySQL的索引和B+tree结构

一句话简单来说,索引的出现其实就是为了提高数据查询的效率,就像书的目录一样。一本 500 页的书,如果你想快速找到其中的某一个知识点,在不借助目录的情况下,那你可能得找一会儿。同样,对于数据库的表而言,索引其实就是它的“目录”。所以,索引就是提高查询速度的数据结构(有序的)。而能提高查询速度的,说明这些数据是按照一定规则排序好的。索引的优缺点提高数据检索效率,降低数据库的IO成本通过索引列对数据进行排序,降低数据排序的成本,降低CPU的消耗索引列也是要占用空间的。

2024-02-29 14:18:22 758

原创 MySQL索引失效与MySQL8新添加的索引特性

因为索引保存的是索引字段的原始值,而不是 id + 1 表达式计算后的值,所以无法走索引,只能通过把索引字段的取值都取出来,然后依次进行表达式的计算来进行条件判断,因此采用的就是全表扫描的方式。创建联合索引时,我们需要注意创建时的顺序问题,因为联合索引 (a, b, c) 和 (c, b, a) 在使用的时候会存在差别。而条件的左侧使用了占位符,导致无法按照正常的目录进行匹配,导致索引失效就很正常了。这里却是使用了索引。因为索引保存的是索引字段的原始值,而不是经过函数计算后的值,自然就没办法走索引了。

2024-02-29 13:33:48 771

原创 MySQL的事务与隔离级别

数据库中的事务是指对数据库执行一批操作,而这些操作最终要么全部执行成功,要么全部失败,不会存在部分成功的情况。这个时候就需要用到事务。最经典的例子就是转账,你要给朋友小白转 1000 块钱,而此时你的银行卡只有 1000 块钱。转账过程具体到程序里会有一系列的操作,比如查询余额、做加减法、更新余额等,这些操作必须保证是一体的,不然等程序查完之后,还没做减法之前,你这 1000 块钱,完全可以借着这个时间差再查一次,然后再给另外一个朋友转账,如果银行这么整,不就乱了么?这时就要用到“事务”这个概念了。

2024-02-27 13:54:32 669

原创 MySQL的SQL语句

这是操作数据库和表的定义的。

2024-02-26 15:08:45 875 1

原创 MySQL中char和varchar的区别

表中只有单列字段情况下,varchar一般最多能存放(65535 - 3)个字节,varchar的最大有效长度通过最大行数据长度和使用的字符集来确定,通常的最大长度是65532个字符(当字符串中的字符都只占1个字节时,能达到65532个字符);而这也有个情况,不是每次都是开辟80字节的空间来存储的。从这个实验来看,是这样:要是插入的大小不足设置的数值20(这里char(N)的N是20),就只开辟20字节的空间存储,超过20字节了,就开辟实际大小的空间来存储(1e就是十进制30)。

2024-02-26 11:04:41 643

原创 RPC教程 7.服务发现与注册中心

主流的注册中心 etcd、zookeeper 等功能强大,与这类注册中心的对接代码量是比较大的,需要实现的接口也很多。另外,也要提供 Heartbeat 方法,便于服务启动时定时向注册中心发送心跳(也是通过HTTP),默认周期比注册中心设置的过期时间少 1 min。首先定义 GeeRegistry 结构体,默认超时时间设置为 5 min,也就是说,任何注册的服务超过 5 min,即视为不可用状态。而现在我们实现了注册中心,那这一节的服务发现就可以继承上一节的,并添加与注册中心相关的细节。

2024-01-28 10:03:28 1681 2

原创 RPC教程 6.负载均衡

一般来说负载均衡器是独立的, 被放置在服务消费者和提供者之间. 代理通常需要保存请求响应副本, 因此有性能消耗也会造成额外延迟. 当请求量大时, lb (load balance)可能会变成瓶颈, 并且此时 lb 单点故障会影响整个服务。LB能力被分散到每一个服务消费者的进程内部,同时服务消费方和服务提供方之间是直接调用,没有额外开销,性能比较好。假设有多个服务实例,而每个实例都提供相同的功能,为了提高整个系统的吞吐量,每个实例部署在不同的机器上。需要负载均衡那就需要有多个提供相同功能的服务实例。

2024-01-27 18:28:44 1145

原创 RPC教程 5.支持HTTP协议

为了解决这个问题,浏览器通过 HTTP 明文形式向代理服务器发送一个 CONNECT 请求告诉代理服务器目标地址和端口,代理服务器接收到这个请求后,会在对应端口与目标站点建立一个 TCP 连接,连接建立成功后返回 HTTP 200 状态码告诉浏览器与该站点的加密通道已经完成。这里是接管 HTTP 连接,其指这里接管了 HTTP 的 TCP 连接,也就是说 Golang 的内置 HTTP 库和 HTTPServer 库将不会管理这个 TCP 连接的生命周期,这个生命周期已经划给 Hijacker 了。

2024-01-27 18:17:03 1349

原创 RPC教程 4.超时处理机制

超时处理是 RPC 框架一个比较基本的能力,如果缺少超时处理机制,无论是服务端还是客户端都容易因为网络或其他错误导致挂死,资源耗尽,这些问题的出现大大地降低了服务的可用性。等待服务端处理时,等待处理导致的超时(比如服务端已挂死,迟迟不响应)调用映射服务的方法时,处理报文导致的超时。读取客户端请求报文时,读报文导致的超时。从服务端接收响应时,读报文导致的超时。发送请求到服务端,写报文导致的超时。发送响应报文时,写报文导致的超时。与服务端建立连接,导致的超时。

2024-01-22 10:12:46 1321

原创 RPC教程 3.服务注册

这一节要熟悉Go中的反射reflet,不然可能比较难理解。在使用到反射的一些函数时候,我也会讲解关于反射的这个函数的用法。到这里,和官方的net/rpc库已经接近了,已实现rpc基础的重要部分。前面的代码例子,总结下主要2步:1.注册服务,并启动rpc服务,2.创建rpc客户端,客户端发起请求Call.注册服务通过newService方法新建服务,通过reflect获取服务的结构体名,类型等等,之后调用(service.) registerMethods方法来获取可以导出的方法,然后存储在服务端。

2024-01-22 10:08:44 1191

原创 RPC教程 2.支持并发与异步的客户端

封装结构体 Call 来承载一次 RPC 调用所需要的信息。Seq uint64请求的服务以及方法名请求参数和请求的回复请求出错时返回的错误信息为了支持异步调用,Call 结构体中添加了一个字段 Done,Done 的类型是chan *Call,当调用结束时,会调用通知调用方。

2024-01-20 20:08:03 1136

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除