自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 go内存返还系统相关代码

在go中内存返还系统相关代码主要由sysUnusedOS实现在Linux中默认是通过madvice方法的_MADV_FREE进行释放,在这种释放中内存其实是被延迟回收的。sysUnusedOS被scavengeOne调用,scavengeOne在给定的内存块(chunk)中搜索可回收的连续页面,并尝试回收指定数量的内存值得注意的是,在回收之后内存还是可以再次分配的scavengeOne继而被scavenge调用该过程分块进行,从最高地址开始,一直持续到清除指定字节数(nbytes)或耗尽堆。

2024-07-05 21:00:00 751

原创 Golang栈空间管理

连续栈核心原理是当当前栈内存不足时,会触发中断,从而分配更大充足的栈空间,并迁移原栈内容到新栈。此外,除了扩容,连续栈还会在已使用的栈空间未超过了总可用空间的四分之一,将新栈收缩到原来的一半。在Go1.3之前,所有goroutine在初始化时都会分配一块固定大小的内存空间。分段栈能够按需为当前goroutine分配内存,并及时减少内存占用,但。迁移过程会被指针也同样迁移过来,不过没关系根据逃逸分析不变性——,所以指向栈中变量的指针只能在栈上。与堆类似,栈也有全局和局部栈空间。

2024-07-05 20:30:00 259

原创 Go堆内存管理

heapArena: heapArena 是由 mheap 管理的更小的内存块。按 Span class 对 Span 分类,串联成链表,当 mcache 的某个级别 Span 的内存被分配光时,它会向 mcentral 申请 1 个当前级别的 Span。微分配器将多个微小块分配请求合并到同一个内存块中,只有当内存块中的所有对象都需要被回收时,整片内存才可能被回收。mcache: 每个P所有的cache,包含多个空闲内存块链表,不同的链表上的内存块大小可能是不相同的。Go按照不同对象大小有不同的分配逻辑。

2024-07-05 14:48:04 827

原创 Linux文件数据写入

结构体fdfd也就是文件描述符,用于标识已经打开的文件、管道、socket等。是进程和内核的桥梁,允许进程执行各种文件操作struct fd { struct file *file; unsigned int flags;};fileLinux内核中表示打开文件的结构体,包含了文件操作所需的各种信息和元数据。这是文件系统操作的核心结构之一,允许内核跟踪每个打开的文件及其相关的状态。struct file { // 用于链接或者引用计数 union { // 链表节点

2024-07-02 22:45:00 975

原创 Linux自旋锁

面对没有获取锁的现场,通常有两种处理方式。本文主要讲述自旋锁自旋锁其实是一种很乐观的锁,他认为只要再等一下下锁便能释放,避免了操作系统进程调度和线程切换。

2024-06-17 21:15:00 1250

原创 go string 实现

在go中string是不可变的,这意味着对string发生改变的操作实际上都是通过分配新的string去实现的在string内存分配上,对于小对象分配到栈,大对象分配到堆中string在go中的结构其实很简单,就是一个指向实际数据的指针以及字符串的长度。

2024-05-24 17:53:45 320

原创 golang http2客户端处理逻辑分析

流的状态会随着帧(Frame)的发送和接收而改变。客户端连接通过判断是否超出最大并发流限制去创建新流处理,一个请求通过是否有可复用的客户端连接来判断是否要重新创建,而流是不能被复用的。连接池中不存在已经建立的连接,或者连接不能再承载新请求了(比如已经创建的流数量+等待的请求*2已经超过了int32的最大值)客户端连接在创建之后,开启新协程,从帧处理器循环读取帧,流的缓存管道绑定响应体后,数据被添加到对应流的缓存管道中。一个客户端连接对应一个网络连接,一个客户端连接对应多个流,而一个请求对应一个流。

2024-05-17 14:01:25 767

原创 单核CPU调度

相反,如果一个任务“想”在一个配额的时间片上使用更多的内核,它就会在短时间内使用多于配额的内核,然后进入节流状态,也就是说基本上进入睡眠状态,以保持它的摊销内核使用量低于配额,这对于尾延迟来说是灾难性的。调度类是表示一种特定的调度策略和算法,定义了如何选择下一个要运行的任务,如何将任务插入到运行队列中,以及如何处理任务的唤醒和睡眠等。CFS调度利用红黑树优先调度执行总时间更低的,在每次时间片执行完会对执行的进程累加执行时间,并重新选择最低执行时间的进程进行执行。这也就意味着执行越久,执行优先级越低。

2024-05-12 09:14:41 676

原创 golang testing使用

汇报自定义度量值如果度量值是每次迭代的,你应该将其除以b.N。按照惯例,单位应该以 “/op” 结尾。会覆盖同一单位的任何先前报告的值。如果单位是空字符串,或者单位包含任何空格,会引发 panic。如果单位是基准测试框架本身通常报告的单位(如 “allocs/op”),会覆盖该度量值。将 “ns/op” 设置为 0 将禁止该内置度量值。for i := 0;i < b.N;

2024-05-07 21:15:00 970

原创 golang 随机数演化

Source接口定义为缩短的63位,这并不是现代生成器的uint64。

2024-05-07 20:15:00 459

原创 golang netpoller揭秘

netpoller依托于go调度器,提供了一种看上去同步的异步网络编程模式,显著地降低了开发难度更重要的是,go主动挂起goroutine等待网络IO的完成,而不是被动让系统线程去挂起,这就将执行网络IO的goroutine掌控在Go运行时中。

2024-04-28 22:30:00 629

原创 golang sync pool

sync.Pool是内置对象池技术,可用于缓存临时对象,避免因频繁建立临时对象所带来的消耗以及对GC造成的压力在很多知名框架中都可以看到sync.Pool的大量使用。比如Gin中用sync.Pool来复用每个请求都会创建的对象但是值得注意的是sync.Pool缓存的对象可能被无通知的清理。

2024-04-25 15:04:37 939

原创 VLL: a lock manager redesign for main memory database systems阅读

VLL锁管理结构由储存到每个原始数据的的未完成锁写请求数量CX和未完成锁读请求数量CS中心事务请求全局队列TxnQueue组成。

2024-04-12 18:20:06 423

原创 KMP算法理解

之所以储存下一个的原因在于,在进行匹配时,模式串要跳到上一个匹配成功的位置,而字符串本身不会移动,那么在这种情况下,当前字符串要匹配的就是已经匹配成功字符的下一个位置。比如对于字符串"abab",其前缀有a、ab、aba,后缀有b、ab、bab,显然最长公共前后缀就是ab。next[i]储存了在以i为开头的后缀,和以j为结尾的前缀匹配时,j的下一个位置。正如next名字所暗示的,下一个,而不是匹配的j本身。在获取到next数组之后,就直接获取到了如果不匹配情况下,模式串该如何走。

2024-03-26 18:13:29 251

原创 如何实时计算数据流中位数

创建一个最小堆和最大堆,其中最小堆的最小值比最大堆的最大值还大,并使最小堆最大堆数量保持均衡,那么中位数边取乎于最小最大堆堆顶。最容易想到的思路就是直接将所有数据进行排序,然后取排序之后的中位数。不过具体的排序思路也有几种。

2024-03-18 11:42:44 363

原创 Mysql 数据如何储存?

我们知道varchar类型的列最多允许65535字节,在允许NULL的情况下最多储存65532字节,因为NULL标识符占1字节,真实长度数量占2字节。此外,65532这个限制是所有varchar列的长度总和,也就是如果存在多个varchar字段,虽然单个没有超出限制,但这多个字段如果合起来超出了限制,那还是会无法创建的。之所以是记录到下条真实数据的偏移量,而不是下条数据偏移量的原因在于可以利用局部性将前面数据的逆序储存的字段长度、NULL值列表缓存起来,减少数据再次查询硬盘次数。

2024-03-18 11:40:35 1701

原创 PacificA: Replication in Log-Based Distributed Storage Systems阅读

PacificA是微软实现的强一致性的分布式共识协议,用于局域网中基于log的大规模储存系统遵循以下原则有以下前提条件系统仅发生fail-stop错误fail-stop是系统组件仅停止运行,而没有其他额外的错误行为消息可能丢弃或者重排,但不会被修改网络分区也可能发生不同服务器上的时钟不一定同步,甚至不一定是松散同步的,但是时间漂移有上限。

2024-02-23 18:50:39 869

原创 kafka 生产者消费者设计思考

如果采用消费者ack的模式,也就是消费者消费完成之后发送确定消息,那么如果消费者在发送ack的时候也失败了,这就会导致重复消费问题。很可惜,kafka最多只能支撑生产者不发送重复的消息,如果是上述场景中消费者没有ack成功导致的重复消费,还是要进行额外幂等处理的。如果broker在发送消息后,立刻认为消息已经被消费了,那么在传输未到达等原因引发的消费未处理情况会使得这样的认为并不正确。为了避免这些问题,kafka将消息划分到有序的分区中,那么只要记录每个分区被每个消费者组消费数据即可。

2024-02-22 15:08:00 705

原创 文档协作技术——Operational Transformations简单了解

OT是支持协作软件系统的一种广泛使用的技术。OT通常使用副本文档储存,每个客户端都拥有对文档的副本。客户端在本地副本以无锁非堵塞方式操作,并将改变传递到其他客户端。当客户端收到其他客户端传播的改变之后,通过转换应用更改,从而保证一致性初始文档为"abc",并存在客户端A、BA发起操作O1=insert[0, “x”],在位置0插入字符xB发起操作O2=delete[2, “c”],在位置2删除字符c。

2024-02-07 15:09:46 1003 1

原创 algo-桶排序

桶排序是一种分布排序,将元素数组分到多个桶内,然后每个桶再分别进行排序。其计算复杂度取决于对桶内排序所用算法、使用桶数量以及输入均匀度。主要流程如下。

2024-02-04 18:05:04 919

原创 golang sudog是什么?

sudog代表在等待队列中的goroutine,比如channel发送接受。由于goroutine和同步对象的关系是多对多,因此需要sudog映射。

2024-02-02 15:34:03 837

原创 sync.Cond 源码分析

sync.Cond采用一个L锁进行保护条件变量,并使用通知队列来堵塞和通知goroutine。

2024-02-02 15:30:51 437

原创 为什么golang不支持可重入锁呢?

而其他需要用到的场景,可以通过参数控制是否加锁、或者将递归调用函数提取到新函数中交予新函数加锁、或者采用channel之类的来迂回达成可重入锁的目的。那么在实际开发工程中就可能存在虽然是同一个goroutine运行,但是在一个方法内很难知道其他方法是否也用了这个锁,用来做什么。那么重入锁在此时便无法保证保护不变量。比如说存在两个接口方法A、B,A中调用了B,但是由于这两个方法都可能被其他方法所调用,所以如果没有可重入锁便可能会死锁。在工程中使用锁的原因在于为了保护不变量,也可以用于保护内、外部的不变量。

2024-02-01 18:22:24 1184

原创 algo-水塘抽样

水塘抽样是一组随机算法,通过替换k个样本,从未知大小的n个总体中选择随机样本。

2024-02-01 16:29:30 835

原创 Redis锁的使用姿势

考虑到redis主从同步集群中,如果从master获取到锁之后,就故障换成了从节点,那么就会导致锁失效,因此提出了RedLock的分布式锁算法。该算法依赖于这样的假设:虽然进程之间没有同步时钟,但每个进程中的本地时间几乎以相同的速率更新,与锁的自动释放时间相比,误差很小。在上述锁中,存在一个问题——如果A获取了锁,但是由于执行时间过长,导致B也获取到过期后的锁,此时并会同时存在多方获取锁。以下是删除特定value的锁的lua脚本,这样就可以防止删除不属于自己的锁。在锁竞争比较激烈情况下,性能损耗较大。

2024-02-01 16:07:44 399

原创 Redis stream特性了解

在发布订阅中我们了解到发布订阅模式存在的无法持久化保存消息和对于离线重连的客户端不能读取历史消息的缺陷,以下就来了解一下stream是如何解决这个问题的steam是类似于仅添加log的数据结构,提供了以下基本命令XADD: 添加新条目到streamXREAD: 读取条目XDEL: 根据id删除消息DEL: 删除streamdel skeyXRANGE: 返回范围内的条目XLEN: 返回流的长度xlen skeyXINFO: 展示stream的信息。

2024-02-01 11:26:08 880

原创 Redis发布订阅怎么用?

而基于模式的订阅是通过pubsub_patterns的链表去实现的。订阅时创建包含客户端信息和模式的pubsub_patterns,并添加到链表中。发布订阅的实现其实是通过key为频道value为储存订阅频道客户端的字典的链表去实现的,发布时直接遍历所在频道的链表进行消息发送。在发布时,就会遍历该链表检查是否匹配模式,然后发送消息给匹配客户端。

2024-01-29 19:07:09 510

原创 golang map真有那么随机吗?——map遍历研究

在随机选取map中元素时,本想用map遍历的方式来返回,但是却并没有通过测试。那么难道map的遍历并不是那么的随机吗?以下代码参考go1.18hiter是map遍历的结构,主要记录了当前遍历的元素、开始位置等来完成整个遍历过程mapiterinit为开始遍历的方法,主要是确定初始遍历的位置从上面的代码分析我们便可以看出随机选取的元素并不是真的随机,溢出桶并不包含在随机选择的范围里面在具体的遍历过程,存在以下疑问通过以上代码分析,可以看出:在扩容时遍历,如果当前遍历的桶已经迁移好了,那么取新桶。

2024-01-25 22:45:00 1002

原创 什么是线段树?

线段树是用于储存区间信息的数据结构。线段树将区间划分为左右子区间进行递归求解,便形成了树形结构。并通过合并两区间信息从而取得任意区间信息例如对于数组a={10, 11, 12, 13, 14},那么就可以构建以下线段树。

2024-01-23 19:10:21 461

原创 Mysql如何快速插入10亿条数据呢?

若一组任务堆积量太大,或者堆积时间太长,则让其他工作节点每处理完一批本组数据,便要处理该堆积数据,直到该堆积数据低于阈值量或者阈值时间。设置一个批次插入为一个任务,在此定每次插入1000条数据,那么每个文件总共就是1w个任务,这1w个任务便为一个任务组。工作节点收到数据后,连接数据库,根据负载情况开启多线程对所接收任务,以任务ID组合行数作为表id进行插入数据。工作节点完成本节点绑定的所有任务之后,便可以开始抢占其他节点任务,以未完成量最多的任务组为优先。超过该任务数,进行抢占其他任务组或者等待。

2024-01-23 19:06:11 915

原创 基数排序简单了解

基数排序是根据数字每一位从低到高去进行分类排序的比如对于数组[1, 11, 2, 12],从个位数开始,1和11分到了桶1,2和12分到了桶二,接着十位数,1和2分到了一桶,但由于在上一次分桶中,2在1之后,所以这个顺序仍然会保留,11和12也是一样,因此最后得到正确的有序数组[1, 2, 11, 12]

2023-12-06 15:05:05 131

原创 algo-多数排序

多数排序在leetcode只是一个简单题,但是衍生出来的多种解法却非常有意思首先是最容易想到的hash和排序算法,接着是。

2023-12-06 14:21:09 102

原创 algo-H指数2

如果引用数为x,所在位置为i,那么至少有n-i个引用数不小于x。那么如果x不小于n-i,则意味着有可能取得更大的hIndex,最小符合h指数的边界应该向左移动。

2023-12-05 10:25:32 107

原创 数据库相关算法题 V3

更好的办法,已知期望配送日期一定不早于下单日期,那么只要用户的首单日期与最小的期望配送日期相等,那么这个首单就是即时订单。那么只需要对count()、sum()做些小小改变,count()会忽略null,那么如果都是null,返回值也就是0了;sum()如果都是null,才会返回null,那么只要在无值的时候返回0就可以了。我最初的方案原本如下,就是根据国家区域和月份分组聚合,但是忽略了在没有匹配数据的情况下sum()、count()会返回null。此外也可以根据month、group分组。

2023-12-03 23:35:45 131

原创 数据库相关算法题 V2

为了解决这点我们可以用上聚合函数min()去做到,如果不用的话,将会导致取到顺序的第一个登陆日期,而不是我们期待的第一次登陆日期,本题关键在于如何判断数字是连续出现的,诀窍在于采用三表连接,表a、b、c的id分别是连续的,并且num相等。两个条件就是两个子查询,我们只需要在子查询中找到所有满足条件的数据就可以了。与方法1思想类似,也是统计大于等于分数的个数,只不过是采用同表连接。在本题中,如何在group中取第一次登陆日期将是难点所在。以大于本分数的数量作为rank。如何输出相应的rank?

2023-12-03 10:13:30 127

原创 数据库相关算法题 V1

超过经理收入的员工显然是要将同一张表,作为经理和员工表连接。这里存在两种方法,一种是采用WHERE。居然不能select后update,还要通过一个中间表去解决。本题的关键在于多表连接,三表之间的连接与两表是一致的。对于前者直接采用distinct关键字,而后者可以。本题的关键点在于过滤掉重复的以及null的处理。最先想到的方法是找到所有订购过的,然后排除。另一种巧妙的方法是左连接筛选。另一种是使用JOIN。

2023-12-02 16:29:48 148

原创 make和new的区别

make和new都是golang用来分配内存(理论上都是在堆上分配),不同的是。

2023-10-30 16:19:26 103

原创 在关系型数据库中储存树形结构

嵌套集合模型是根据遍历树对节点进行编号,遍历树对每个节点进行两次访问,按访问的顺序分配编号,并且在两次访问时都进行编号。更新需要重新编号,因此代价很高。比如对于下表中的mac air m2是第3步时发生了第一次访问,同时由于是最左子节点,因此会发生返回,那么第4步发生了第二次访问。对于查询就相对比较麻烦了,需要通过like之类的,并且完整路径很有可能会超出索引的最佳长度,对查询性能有损耗。nested set方法查询删除所有子节点非常快,然而模型较为复杂,插入移动极为麻烦,需要重建left、right。

2023-09-27 11:10:16 125

原创 Mysql Join 多条件的小坑

其实从left join的原义也可以知道,会保留join时左表的所有项,那么就不应该在join的时候将左表数据筛选掉。而右表本来是能够筛选的。一般情况我们可能只在join on 后面添加唯一的关联条件,但是如果在on后面添加多个条件会发生什么呢?但是对于left join,情况就比较微妙了。表现与在where后面添加条件一致。对于inner join。

2023-09-21 23:22:58 342

原创 Linux硬链接、软链接

硬链接是一个目录条目(在基于目录的文件系统中),它将一个名称与一个文件关联起来。因此,每个文件必须至少有一个硬链接。为文件创建额外的硬链接可以使该文件的内容可以通过额外的路径访问(即通过不同的名称或在不同的目录中)这会导致别名效应(alias effect):进程可以通过任意路径打开文件并修改其内容。相比之下,文件的软链接或“快捷方式”不是指向数据本身的直接链接,而是指向一个硬链接或另一个软链接的引用。在我看来硬链接可以理解为数据的指针,而软链接则是指针的指针。

2023-09-20 23:40:33 435

空空如也

空空如也

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

TA关注的人

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