- 博客(134)
- 收藏
- 关注
原创 Redis 删除数据后,为什么内存占用率还是很高
Redis删除数据后内存占用高Redis数据删除后,Redis释放的内存空间会有内存分配器管理,并不会立即返回给操作系统。所以操作系统看到的内存占用依然很高Redis释放的空间不连续,导致这些空间有可能处于一种限制的状态,导致有空闲空间但是Redis却不会存数据内存碎片形成原因操作系统的内存分配: 内存分配器一般是按固定大小来分配内存,而不是完全按照应用程序申请的内存空间大小给程序分配Redis的负载特征:大小不同的键值对,申请内存分配时,本身就会有大小不一样的空间需求判断内存碎片
2021-07-27 11:40:37 498
原创 波动的响应延迟:如何应对变慢的Redis?
Redis基线性能系统在低压力、无干扰下的基本性能,这个性能只由当前的软硬件配置决定redis-cli --intrinsic-latency 120 -h host -p 6379120秒统计基线性能,打印出的最大延迟就是基线性能如果Redis运行时的延迟是基线性能2倍以上,就可以认定为Redis慢了Redis变慢原因与应对Redis自身操作特性文件系统操作系统Redis自身操作特性慢查询命令过期key操作慢查询命令用其他命令代替 smembers替换为sscan需
2021-07-26 17:01:20 327
原创 Redis 异步机制:如何避免单线程模型的阻塞?
影响Redis性能的5大方面的潜在因素Redis内部的阻塞式操作CPU核和NUMA架构的影响Redis关键系统配置Redis内存碎片Redis缓冲区Redis实例有哪些阻塞点客户端:网络IO,键值对增删改查操作,数据库操作磁盘:生成RDB快照,记录AOF日志,AOF日志重写主从节点:主库生成、传输RDB文件,从库接收RDB文件,清空数据库,加载RDB文件切片集群实例:向其他实例传输哈希槽信息,数据迁移客户端操作阻塞点网络IO部分,redis使用IO多路复用机制,避免主线程一
2021-07-24 15:29:44 393
原创 GRPC 整理
gRPC 是什么高性能,开源通用的RPC框架RPCRPC(remote procedure call 远程过程调用)框架提供了一套机制,使得应用程序之间可以进行通信,而且也遵从server/client模型。使用的时候客户端调用server端提供的接口就像是调用本地的函数一样gRPC优势遵循http 2.0协议通过protobuf定义接口,限制更严格通过二进制编码数据,减少传输数据量,提升性能更方便的支持流式通信...
2021-07-23 14:31:12 180
原创 有一亿个keys要统计,应该用哪种集合?
常用集合统计模式聚合统计排序统计二值状态统计基数统计聚合统计指统计多个集合元素的聚合结果统计多个集合的共有元素(交集统计)把两个集合相比,统计其中一个集合独有的元素(差集统计)统计多个集合的所有元素(并集统计)排序统计list或者sorted_set类型有序统计二值状态统计指集合元素的取值就只有 0 和 1 两种bitmap,用 String 类型作为底层数据结构实现的一种统计二值状态的数据类型基数统计统计就是指统计一个集合中不重复的元素个数set集合类
2021-07-20 16:02:59 151
原创 切片集群:数据增多了,是该加内存还是加实例?
数据量大之后,redis响应时间变长使用 RDB 进行持久化时,Redis 会 fork 子进程来完成,fork 操作的用时和 Redis 的数据量是正相关的fork 在执行时会阻塞主线程。数据量越大,fork 操作造成的主线程阻塞的时间越长切片集群启动多个 Redis 实例组成一个集群,然后按照一定的规则,把收到的数据划分成多份,每一份用一个实例来保存redis数据量增多的两种方案纵向扩展 scale up: 升级单个 Redis 实例的资源配置,包括增加内存容量、增加磁盘容量、使用
2021-07-16 16:56:20 183
原创 哨兵集群:哨兵挂了,主从库还能切换吗?
哨兵集群组成和运行机制基于 pub/sub 机制的哨兵集群组成基于 pub/sub 机制的哨兵集群组成哨兵之间可以互相发现,使用了Redis 提供的 pub/sub 机制,也就是发布 / 订阅机制。哨兵只要和主库建立起连接,就可以在主库上发布消息,比如说发布自己的连接信息(IP 和端口)可以从主库上订阅消息,获得其他哨兵发布的连接信息。当多个哨兵实例都在主库上做了发布和订阅操作后,它们之间就能知道彼此的 IP 地址和端口只有订阅了同一个频道的应用,才能通过发布的消息进行信息交换哨兵订阅_
2021-07-16 15:45:34 209
原创 哨兵机制:主库挂了,如何不间断服务?
哨兵机制解决问题主库是不是真的挂了用哪个从库做为主库新主库怎么通知给其他从库哨兵机制流程哨兵就是一个运行在特殊模式下的Redis进程,主要负责:监控、选择主库和通知监控:哨兵进程在运行时,周期性地给所有的主从库发送 PING 命令,检测它们是否仍然在线运行主管下线和客观下线主观下线:哨兵进程会使用 PING 命令检测它自己和主、从库的网络连接情况,用来判断实例的状态。如果哨兵发现主库或从库对 PING 命令的响应超时了,那么,哨兵就会先把它标记为“主观下线”。检查从库使用主管下线
2021-07-16 14:33:44 172
原创 数据同步:主从库如何实现数据一致?
Redis高可靠性数据尽量少丢失服务尽量少中断Redis主从模式,读写分离读操作: 主库和从库都可以写操作:首先主库执行,然后主库将操作同步给读库通过 replicaof(Redis 5.0 之前使用 slaveof)命令形成主库和从库的关系 replicaof 主库ip 主库端口全量复制,主从长链接,增量复制全量复制时,基于硬盘复制,和socker复制(无盘复制)Redis主从库的复制是异步的,主库收到命令操作后,在本地执行完成后,就会返回给客户端,并不会等到和从库同步完成后才返回
2021-07-15 17:38:14 330 1
原创 内存快照:宕机后,Redis如何实现快速恢复?
RDB内存快照Redis DataBase内存快照:内存中的数据在某一个时刻的状态记录,某一时刻的状态以文件的形式写到磁盘上,也就是快照恢复数据时可以把RDB文件直接读入内存,很快的完成恢复对哪些数据做快照全量数据生成RDB命令save:在主线程中执行,会导致阻塞bgsave: 创建一个子进程,专门用于写入 RDB 文件,避免了主线程的阻塞,这也是 Redis RDB 文件生成的默认配置快照时数据能修改吗可以修改Redis 就会借助操作系统提供的写时复制技术(Copy-O
2021-07-15 17:37:45 227
原创 AOF日志:宕机了,Redis如何避免数据丢失?
Redis持久化机制AOF append on fileRDB 快照AOF实现原理写后日志先写内存数据,再记录日志命令执行后才记录日志,不会阻塞当前的写操作。记录内容AOF 里记录的是 Redis 收到的每一条命令,这些命令是以文本形式保存的。以 “set testkey testvalue”命令后记录的日志为例,“*3”表示当前命令有三个部分,每部分都是由“$+数字”开头,后面紧跟着具体的命令、键或值。这里,“数字”表示这部分中的命令、键或值一共有多少字节。例如,“$3 set
2021-07-13 17:26:40 138
原创 高性能IO模型:为什么单线程Redis能那么快?
单线程 or 多线程?Redis 是单线程,主要是指 Redis 的网络 IO 和键值对读写是由一个线程来完成的,这也是 Redis 对外提供键值存储服务的主要流程Redis 的其他功能,比如持久化、异步删除、集群数据同步等,其实是由额外的线程执行的为什么单线程?多线程编程模式面临的共享资源的并发访问控制问题。单线程不用解决数据共享问题单线程为什么快?Redis 的大部分操作在内存上完成,再加上它采用了高效的数据结构,例如哈希表和跳表,这是它实现高性能的一个重要原因Redis 采用
2021-07-12 17:09:23 137
原创 数据结构:快速的Redis有哪些慢操作?
一、底层数据结构简单动态字符串双向链表压缩列表哈希表调表整数数组二、键和值用什么结构组织?Redis 使用了一个哈希表来保存所有键值对。一个哈希表,其实就是一个数组,数组的每个元素称为一个哈希桶。所以,我们常说,一个哈希表是由多个哈希桶组成的,每个哈希桶中保存了键值对数据,哈希桶中的元素元素保存的并不是值本身,而是指向具体值得指针哈希表的最大好处很明显,就是让我们可以用 O(1) 的时间复杂度来快速查找到键值对——我们只需要计算键的哈希值,就可以知道它所对应的哈希桶位置,然后就可以访
2021-07-10 16:43:04 139 1
原创 Golang调度器的设计策略
1 复用线程work stealing 线程偷取其他P的Ghand off 机制 当前M的G阻塞的时候,切换P到其他的M继续执行2 利用并行限定P的个数,每个P的本地队列最多有256个GCPU核心数/23 抢占每个G最多运行10ms超过10ms抢占模式4 全局G队列全局G队列获取时加锁解锁...
2021-05-13 18:37:58 218
原创 Mysql为什么使用B+树,而不是B树
B树特点树的每个结点都会存储数据单次查询不一定要遍历到树的根部,平均查询时间会比较快B+树特点树的叶子节点才真正存储数据查询每次都要访问叶子节点,查询比较稳定每个叶子节点互相链表相连,保证了范围查询的时效性为什么使用B+树而不是用B树范围查询B+树明显优于B树因为B数据每个节点都存储数据,每次查询的数据大小固定,就会造成每次查询返回的数据的条数变少,相同数据规模的情况下B树会增加io次数,而B+树,则数据量较小,一次可以返回多条记录,io次数较少...
2021-04-28 15:54:55 1546
原创 Redis事务与MySQL事务对比-简述
Redis事务一次可以执行多个命令批量操作在发送 EXEC 命令前被放入队列缓存收到 EXEC 命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行(语法错误会停止事务)事务执行过程中,不会有其他操作插入到事务的执行命令序列中单个redis命令的执行时原子性的,但是事务上没有维持原子性可以理解为打包执行,省去网络耗时,中间某条指令失败不会导致之前操作回滚,不会导致后续操作暂停redis通过watch来监测数据,在执行exec前,监测的数据被其他人更改会抛出错误,取消执行MyS
2021-04-25 18:47:09 251
原创 InnoDB数据页(索引页)结构
页结构记录头信息delete_mask0:没有删除1:删除min_rec_mask: B+树的每层非叶子结点中的最小记录都会添加该标记n_owned: 该记录拥有多少条记录,也就是该组内共有几条记录,看下边的目录页heap_no: 当前记录在页中的位置0:伪记录,最小记录,为01:伪记录,最大记录,为1最大记录和最小记录不存储在user-records中,放在单独的Infimum + Supremum中record_type:当前记录的类型0:普通记录1:B+树非
2021-04-23 15:55:57 261
原创 分库分表
垂直分表:将一个表按照字段分成多表,每个表存储其中一部分字段。可以将商品表中的商品详情字段拆分成单独一个表把不常用的字段单独放在一张表;把text,blob等大字段拆分出来放在附表中;经常组合查询的列放在一张表中;热门数据操作效率提高磁盘使用情况减少垂直分表只解决了单一表数据量过大的问题,但没有将表分布到不同的服务器上,因此每个表还是竞争同一个物理机的CPU、内存、网络IO、磁盘。垂直分库:按照业务将表进行分类,分布到不同的数据库上面,每个库可以放在不同的服务器上,它的核心理念是专库专用
2021-04-07 15:47:13 165
原创 Go 为什么快
编译型语言直接编译为机器代码执行,不需要虚拟机执行不需要动态检测变量类型支持跨平台编译内存占用低运行时不需要其他环境变量采用紧凑存储,占用空间较小部署简单编译成二进制文件,不需要服务器安装运行环境并发简单语言级别的并发支持线程安全的channel,使共享数据变得简单并发成本低,线程栈空间通常是2M,协程是2KGMP调度模型...
2021-04-02 16:20:55 186 2
原创 Golang Map为什么是无序的
Map无序底层数据 哈希表,本就是无序的,正常写入(非哈希冲突写入):是hash到某一个bucket上,而不是按buckets顺序写入哈希冲突写入:如果存在hash冲突,会写到同一个bucket上。range遍历的时候随机一个位置开始Map扩容成倍扩容: (元素数量/bucket数量) > 6.5时触发成倍扩容,元素顺序变化等量扩容:溢出桶的数量大于等于 2*B时 触发等量扩容,不会改变元素顺序参考文章为什么说Go的Map是无序的?...
2021-04-02 11:02:08 905
原创 MySQL 临时笔记 待整理
大体来说,MySQL 可以分为 Server 层和存储引擎层两部分Server 层包括连接器、查询缓存、分析器、优化器、执行器等,涵盖 MySQL 的大多数核心服务功能,以及所有的内置函数(如日期、时间、数学和加密函数等),所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图等。而存储引擎层负责数据的存储和提取。其架构模式是插件式的,支持 InnoDB、MyISAM、Memory 等多个存储引擎。现在最常用的存储引擎是 InnoDB,它从 MySQL 5.5.5 版本开始成为了默认存储引擎
2021-04-01 11:54:51 165
原创 HTTP 整理
1. http与https区别HTTP 的URL 以http:// 开头,而HTTPS 的URL 以https:// 开头HTTP 是不安全的,而 HTTPS 是安全的HTTP 标准端口是80 ,而 HTTPS 的标准端口是443在OSI 网络模型中,HTTP工作于应用层,而HTTPS 的安全传输机制工作在传输层HTTP 无法加密,而HTTPS 对传输的数据进行加密HTTP无需证书,而HTTPS 需要CA机构wosign的颁发的SSL证书...
2021-04-01 09:41:04 117
原创 Redis 整理
Redis是什么Redis 是 C 语言开发的一个开源的(遵从 BSD 协议)高性能键值对(key-value)的内存数据库,可以用作数据库、缓存、消息中间件等。它是一种 NoSQL(not-only sql,泛指非关系型数据库)的数据库性能优秀,数据在内存中,读写速度非常快,支持并发 10W QPS。单进程单线程,是线程安全的,采用 IO 多路复用机制。丰富的数据类型,支持字符串(strings)、散列(hashes)、列表(lists)、集合(sets)、有序集合(sorted sets)等。支
2021-04-01 09:40:40 106
原创 数据结构-树
树是什么树是由结点和边组成的,不存在环的一种数据结构。树满足递归定义的特性。也就是说,如果一个数据结构是树结构,那么剔除掉根结点后,得到的若干个子结构也是树,通常称作子树。二叉树是什么在二叉树中,每个结点最多有两个分支,即每个结点最多有两个子结点,分别称作左子结点和右子结点满二叉树:定义为除了叶子结点外,所有结点都有2个子结点完全二叉树:定义为除了最后一层以外,其他层的结点个数都达到最大,并且最后一层的叶子结点都靠左排列二叉树时间复杂度遍历 O(n)增删O(1)查询O(1)树的存
2021-04-01 09:40:22 155
原创 Golang sync.Once
简介Go 标准库提供的使函数只执行一次的实现,常应用于单例模式,例如初始化配置、保持数据库连接等与init区别init 函数是当所在的 package 首次被加载时执行sync.Once 可以在代码的任意位置初始化和调用,可以延迟到使用时再执行,且并发场景下是线程安全的多数情况下,sync.Once 被用于控制变量的初始化,这个变量的读写满足如下三个条件当且仅当第一次访问某个变量时,进行初始化(写)变量初始化过程中,所有读都被阻塞,直到初始化完成变量仅初始化一次,初始化完成..
2021-03-31 17:34:45 187
原创 Redis缓存
缓存穿透:查询不存在的数据,缓存和数据库都查不到,就会一直穿过缓存查询数据库缓存空值,设置过期时间布隆过滤器,判断key是否存在缓存击穿:高并发场景,大量请求查询一个key,当这个key过期时,大量查询落到数据库中,导致数据库压力过大查询数据库加分布式锁,有一个请求落到数据库上,让后其余请求就可以读缓存了缓存雪崩:大量key失效,导致大量查询落到数据库上采用集群,降低服务宕机的概率(待学习)ehcache本地缓存 + Hystrix限流&降级(待学习)...
2021-03-31 17:34:04 88
原创 MongoDB运算符
加法运算符 $add// 数字类型加整数,时间类型加毫秒数> db.users.aggregate([{"$project": {"age": "$age", "birth": "$birth", "birth+10": {"$add": ["$birth", 10]}}}]){ "_id" : ObjectId("601cf85c7cfdb08d65ff4668"), "age" : 20, "birth" : ISODate("2000-04-10T00:00:00Z"), "birth..
2021-03-31 17:33:07 739
原创 MongoDB索引特性
唯一索引值唯一,不能重复db.users.dropIndexes() // 删除全部索引> db.users.find(){ "_id" : ObjectId("601cf85c7cfdb08d65ff4668"), "name" : "n1", "age" : 20, "gender" : "m", "birth" : ISODate("2000-04-10T00:00:00Z"), "pswd" : "password123", "courses" : [ "Golang", "Gor..
2021-03-31 17:32:26 161
原创 MongoDB索引类型
索引类型单字段索引复合索引多key索引文本索引单字段索引> db.users.getIndexKeys() // 查询所有单字段索引的列[ { "_id" : 1 }, { "name" : 1 }, { "age" : -1 } ]// 查询命中索引> db.users.find({"age": 20}).explain(){ "queryPlanner" : { "plannerVersion" : 1, "namespace" : "test
2021-03-31 17:31:50 250
原创 MongoDB索引操作
索引简介索引通常能够极大的提高查询效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录,这种扫描全集合的查询效率时非常低的,特别在处理大量的数据时。索引是特殊的数据结构,索引存储在一个易于便利读取的数据集合中,索引是对数据库中一列或多列的值进行排序的一种结构建立索引后,MongoDB会额外存储一份按字段生序或降序排列的索引数据,索引结构通常采用类似btree的结构持久化存储,以保证从索引里快速(O(logN)的时间复杂度)找出某个值对应的位置信息,然后根据位
2021-03-31 17:31:15 175
原创 MongoDB数据操作
title: MongoDB数据操作date: 2021-02-03 09:41:06tags:MongoDBcategories:MongoDBDatabase数据库管理查看数据库show dbsshow databases创建数据库use 数据库名// 切换到指定的数据库,如果数据库不存在,则会自动创建数据库删除数据库当前用户进入某个数据库,就只能删除某个数据库db.dropDatabase()Collection集合管理MongoDB中集.
2021-03-31 17:30:35 142
原创 MongoDB聚合查询
数据准备db.users.drop()db.users.insertMany([ {"name": "n1", "age": 20, "gender": "m", "birth": new ISODate("2000-04-10"), "pswd": "1"}, {"name": "n2", "age": 21, "gender": "f", "birth": new ISODate("1999-04-10"), "pswd": "2"}, {"name": "n3", "age": 22, "g
2021-03-31 17:29:54 235
原创 MongoDB概述与用户操作
什么是MongoDBMongoDB是一个基于分布式的文件存储的数据库,有C++编写。旨在为web应用提供高性能数据存储解决方案分布式:可以快速进行水平扩容,方便搭建集群文件存储:存储的是文件,落地到磁盘,持久化保存MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库中功能最丰富,最像关系数据库的。支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型。MongoDB最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几..
2021-03-31 17:28:28 157
原创 MySQL 整理
1. 事务四大特性(ACID)原子性、一致性、隔离性、持久性?原子性: 事务是一个整体,要么都完成,要么都失败回滚一致性:事务总是从一个一致性状态转移至另一个一致性状态,事务开始前和结束后,数据库的完整性约束没有被破坏。隔离性:并发时,每个事务之间互相隔离,互不干扰持久性:事务提交后,对数据的修改时永久性的2. 事务的并发?事务隔离级别,每个级别会引发什么问题,MySQL默认是哪个级别?事务隔离级别读未提交:事务可以读到其他事务,没有提交的修改,产生:脏读,不可重复读,幻读读提交:
2021-03-31 17:25:22 105
原创 Golang pprof 工具使用
Golang pprof分析工具使用1. 概述go的pprof工具可以用来监测进程的运行数据,用于监控程序的性能,对内存使用和CPU使用的情况统信息进行分析。官方提供了两个包:runtime/pprof和net/http/pprof,前者用于普通代码的性能分析,后者用于web服务器的性能分析2. runtime/pprof的使用该包提供了一系列用于调试信息的方法,可以很方便的对堆栈进行调试StartCPUProfile:开始监控cpu。StopCPUProfile:停止监控cpu,使用Sta
2021-03-30 20:12:50 535
原创 Golang整理
1. go struct能不能比较如果结构体的所有成员变量都是可比较的,那么结构体就可比较如果结构体中存在不可比较的成员变量,那么结构体就不能比较结构体之间能进行强制转换也可以比较。结构体之间进行转换需要他们具备完全相同的成员(字段名、字段类型、字段个数)指针比较实际上是比较指针指向的内存地址,而不是指针变量的内存地址package mainimport "fmt"type Student struct { Name string Age int Slice []int Map
2021-03-25 11:48:56 130
原创 线程模型
线程模型一对一:一个用户线程对应一个内核线程多对一:多个用户线程对应一个内核线程多对多:多个用户线程对应多个内核线程Golang 协程协程是用户协作式调用线程是抢占式调度
2021-03-24 09:39:19 90
原创 Golang 调度
开始go程序启动,主机上定义的每一个虚拟内核都会为它分配一个逻辑处理器§,每个线程都会分配一个逻辑处理器package mainimport ( "fmt" "runtime")func main() { fmt.Println(runtime.NumCPU()) // MacbookPro 2019 4核心8线程,返回结果8}会为每一个逻辑处理器(P)分配一个M(os线程)线程是OS来处理的,并且OS还负责把线程放置到一个core上去执行每个线程单独连到一个P上Go
2021-03-22 18:42:13 328
原创 Golang 操作系统调度入门
操作系统调度操作系统调度器,它负责确保在有线程能够运行的时候内核不会空闲下来。它会制造一种假象——所有能够跑的线程此时都在同时执行。为此,调度器需要优先执行高优先级的线程,但是它也必须保证低优先级的线程不会饿死。调度器也必须尽可能将调度延时压倒最少线程三种状态等待:线程停止并且等待被唤醒。如等待硬件(硬盘、网络),操作系统(系统调用) 或者是同步调用(atomic,mutexes)可执行:线程想要占用内核上的cpu时间来执行分配给线程的指令执行中:线程已经置于内核中,并且正在执行它的机器指令
2021-03-22 18:06:35 123
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人