- 博客(151)
- 收藏
- 关注
原创 Kafka负载均衡挑战解决
本文为阅读笔记kafka通过利用分区来在多个队列中分配消息来实现并行性。然而每条消息都有不同的处理负载,也具有不同的消费速率,这样就有可能负载不均衡,从而使得瓶颈、延迟问题和整体系统不稳定,进而导致额外的维护工作或额外的资源分配。在 Kafka 中,分区器和分配器策略会影响消息分发。Producer 分区器Consumer 分配器这些策略都是基于两个主要的假设。
2025-04-07 23:54:14
840
原创 RAG了解与实践
RAG(Retrieval-Augmented Generation) 是一种授予生成式人工智能模型信息检索功能的技术。它修改与大型语言模型的交互 (LLM),以便模型响应用户对一组指定文档的查询,使用此信息来增强从其自身庞大的静态训练数据中提取的信息。这允许LLMs使用特定于域和/或更新的信息。可以简单理解为"检索+生成"的人工智能技术。想象你正在做一个复杂的研究项目,除了大脑里已有的知识,你还需要查阅额外的资料来提高回答的准确性和深度。RAG就是AI模型的这个"查阅资料"过程。
2025-03-06 22:34:55
1021
原创 Redis 实现延迟队列的方案
在分布式系统中,延迟队列是一种常见的需求,例如订单超时取消、任务定时执行等。Redis 作为高性能的内存数据库,提供了多种实现延迟队列的方案。本文将介绍几种不同的 Redis 方案,并分析其优缺点及适用场景。
2025-03-04 23:34:51
512
原创 流式抽样唯一元素方案设计
根据不同的应用场景和需求,可以选择不同的流式抽样方案。如果需要高效且简单的实现,可以考虑确定性哈希抽样或布隆过滤器方案;如果对数据量和性能有更高要求,Redis HyperLogLog和分层采样则是更合适的选择;对于需要时间维度分析的场景,可以使用时间窗口 + 一致性哈希方案。
2025-02-27 23:19:53
858
原创 啥是滚动哈希?
滚动哈希(Rolling Hash)是一种,允许在时间内计算的哈希值,而不需要重新遍历整个子串。它常用于字符串匹配、子串查找等问题,比如就是基于滚动哈希的。在说滚动哈希方法之前,先谈谈一般窗口内哈希值是如何计算的例如对于字符串hello,那么哈希值是hashCodehelloh−a∗pow1310e−a∗pow1311l−a∗pow1312l−a∗pow1313o−a∗pow1314。
2025-02-20 23:35:02
653
原创 实验流量统计设计
当我们需要统计实验中每个分支的实际进入次数时,如何设计一个高效、可靠且对业务影响最小的方案,成为了关键。以下是几种常见的流量统计方案的分析与实现设计目标。
2025-02-20 22:48:24
892
原创 如何检测一次性流水线任务处理完成呢?
在任务处理过程中,特别是在多阶段、多线程的流水线任务中,如何检测所有任务是否已经完成是一个常见且关键的设计问题。流水线任务通常涉及多个环节,如管理器、请求器、转换器、导出器等,每个环节处理完毕后将结果传递给下一个环节。当所有环节都完成处理后,任务才算真正完成。本文将探讨几种检测流水线任务处理完成的常见方案,分析其实现步骤、优缺点和适用场景。
2025-02-15 16:14:11
597
原创 高并发读多写少场景下的高效键查询与顺序统计的方案思路
之前在某平台看到一篇有意思的场景——对于高并发读多写少场景下,如何进行高效键查询与统计早于其创建时间且没有被删除的数量(只需要先入先出,不需要从中间删元素)传统的数据库索引或简单的哈希存储难以同时满足这两个需求,尤其是在高并发环境下,如何在不影响查询效率的前提下维持顺序统计成为关键挑战。
2025-02-09 23:36:18
517
原创 elasticsearch是如何进行搜索的?
以 TF - IDF 为例,如果文档中某个词出现的频率高(词频高),但在整个语料库(索引中的所有文档集合)中该词比较少见(逆文档频率高),那么这个词所在的文档相关性得分就会相对较高。例如,在一个美食相关的索引中,如果 “全聚德烤鸭” 这个词在某篇介绍全聚德的文档中多次出现,而在其他文档中很少出现,那这篇文档在以 “烤鸭” 为查询词时相关性得分就会比较高。是一个不变的、独立的倒排索引,储存了文档的字段、倒排表、储存字段以及其他索引元数据。分片会从它的所有 Segment 中收集匹配的文档,并按相关性排序。
2024-12-03 21:49:34
528
原创 Redis集群节点如果出现故障了,会如何处理呢?
此外在哨兵故障检测之外还存有节点自检,目的在于确保节点间通信正常,维护集群状态。以保证其他主节点知晓该主节点已经下线,并且防止从节点同时启动选举。如果手动配置新主节点或者槽迁移恰好碰上了故障选举,使得同一选举期存在多个主节点,那么该如何处理冲突呢?从节点会计算选举期,若获取的票不在本轮选举中,则不会进行计数。NodeID字典序更小的节点将成为唯一的主节点,并递增选举期。若故障节点为主节点,集群尝试从主节点的从节点中选取新主节点。会不会存在一个从节点收到了同主节点的两轮选举的投票呢?主节点在投票一次后,在。
2024-11-23 15:17:48
767
原创 本地缓存少更改、小数据、低一致表的思考
对于那些少更改、小数据的表,以及对一致性要求不高的业务,其实完全可以通过本地缓存将表数据缓存到本地内存中,然后通过定时机制拉取表更新数据直接从内存中获取数据,将会使得查询性能得到巨大的提升,并且由于更改少,数据量小,同时内存压力也不会很大,除了一致性不高外,完全是利大于弊的策略那么如果我想设计这样的本地缓存,该如何进行呢?
2024-10-21 23:53:35
472
原创 从automaxprocs库浅窥Linux容器的资源控制
automaxprocs能够自动调整Go程序中的Goroutine数量,以充分利用系统资源并提高程序的性能。automaxprocs通过读取系统信息,如CPU核心数和Cgroups限制,来动态调整Goroutine的数量automaxprocs获取CPU限额的关键方法在可以看到是先获取到cgroup的实现,然后调用实现方法获取限制获取cgroup2实现如下具体算限制方法如下其实就是取cpu.max文件中指定的限额。
2024-10-11 22:51:40
975
原创 mysql json查询为什么这么快?
在本地测试中我发现了一件令我惊讶的事情,在300w数据量对json字段里面值进行筛选的时间都在100ms左右!那么为什么mysql json查询这么快呢?
2024-09-01 12:23:23
774
原创 如何设计数据库排序字段
在很少会有中间插入或者对查询排序有较高要求的情况:较短间隔的int是更优的方法在中间插入情况较多的时候:可能float类型更为合适链表方法在插入情况较多的时候也是非常适用的,可是查询性能属实太差数据量少:可以用配置文件或者直接在缓存中设置排序。
2024-08-31 09:52:18
520
原创 GO goroutine状态流转
go池是所有拥有goroutine的地方,包括P的runnext、P本地队列和全局队列Gidle -> Grunnable: 初始化g,放入go池Grunnable -> Grunning: 从go池取出,绑定M,执行实际代码Grunning-> Gdead: 解绑M,重置g,重新放入go池-> Gwaiting: 解绑M,等待被唤醒-> Grunnable: 解绑M,放入go全局队列Gwaiting -> Grunable: 被唤醒后放入go池。
2024-08-01 22:42:20
1059
原创 go内存返还系统相关代码
在go中内存返还系统相关代码主要由sysUnusedOS实现在Linux中默认是通过madvice方法的_MADV_FREE进行释放,在这种释放中内存其实是被延迟回收的。sysUnusedOS被scavengeOne调用,scavengeOne在给定的内存块(chunk)中搜索可回收的连续页面,并尝试回收指定数量的内存值得注意的是,在回收之后内存还是可以再次分配的scavengeOne继而被scavenge调用该过程分块进行,从最高地址开始,一直持续到清除指定字节数(nbytes)或耗尽堆。
2024-07-05 21:00:00
860
原创 Golang栈空间管理
连续栈核心原理是当当前栈内存不足时,会触发中断,从而分配更大充足的栈空间,并迁移原栈内容到新栈。此外,除了扩容,连续栈还会在已使用的栈空间未超过了总可用空间的四分之一,将新栈收缩到原来的一半。在Go1.3之前,所有goroutine在初始化时都会分配一块固定大小的内存空间。分段栈能够按需为当前goroutine分配内存,并及时减少内存占用,但。迁移过程会被指针也同样迁移过来,不过没关系根据逃逸分析不变性——,所以指向栈中变量的指针只能在栈上。与堆类似,栈也有全局和局部栈空间。
2024-07-05 20:30:00
369
原创 Go堆内存管理
heapArena: heapArena 是由 mheap 管理的更小的内存块。按 Span class 对 Span 分类,串联成链表,当 mcache 的某个级别 Span 的内存被分配光时,它会向 mcentral 申请 1 个当前级别的 Span。微分配器将多个微小块分配请求合并到同一个内存块中,只有当内存块中的所有对象都需要被回收时,整片内存才可能被回收。mcache: 每个P所有的cache,包含多个空闲内存块链表,不同的链表上的内存块大小可能是不相同的。Go按照不同对象大小有不同的分配逻辑。
2024-07-05 14:48:04
899
原创 Linux文件数据写入
结构体fdfd也就是文件描述符,用于标识已经打开的文件、管道、socket等。是进程和内核的桥梁,允许进程执行各种文件操作struct fd { struct file *file; unsigned int flags;};fileLinux内核中表示打开文件的结构体,包含了文件操作所需的各种信息和元数据。这是文件系统操作的核心结构之一,允许内核跟踪每个打开的文件及其相关的状态。struct file { // 用于链接或者引用计数 union { // 链表节点
2024-07-02 22:45:00
1608
原创 Linux自旋锁
面对没有获取锁的现场,通常有两种处理方式。本文主要讲述自旋锁自旋锁其实是一种很乐观的锁,他认为只要再等一下下锁便能释放,避免了操作系统进程调度和线程切换。
2024-06-17 21:15:00
1430
原创 go string 实现
在go中string是不可变的,这意味着对string发生改变的操作实际上都是通过分配新的string去实现的在string内存分配上,对于小对象分配到栈,大对象分配到堆中string在go中的结构其实很简单,就是一个指向实际数据的指针以及字符串的长度。
2024-05-24 17:53:45
426
原创 golang http2客户端处理逻辑分析
流的状态会随着帧(Frame)的发送和接收而改变。客户端连接通过判断是否超出最大并发流限制去创建新流处理,一个请求通过是否有可复用的客户端连接来判断是否要重新创建,而流是不能被复用的。连接池中不存在已经建立的连接,或者连接不能再承载新请求了(比如已经创建的流数量+等待的请求*2已经超过了int32的最大值)客户端连接在创建之后,开启新协程,从帧处理器循环读取帧,流的缓存管道绑定响应体后,数据被添加到对应流的缓存管道中。一个客户端连接对应一个网络连接,一个客户端连接对应多个流,而一个请求对应一个流。
2024-05-17 14:01:25
1230
1
原创 单核CPU调度
相反,如果一个任务“想”在一个配额的时间片上使用更多的内核,它就会在短时间内使用多于配额的内核,然后进入节流状态,也就是说基本上进入睡眠状态,以保持它的摊销内核使用量低于配额,这对于尾延迟来说是灾难性的。调度类是表示一种特定的调度策略和算法,定义了如何选择下一个要运行的任务,如何将任务插入到运行队列中,以及如何处理任务的唤醒和睡眠等。CFS调度利用红黑树优先调度执行总时间更低的,在每次时间片执行完会对执行的进程累加执行时间,并重新选择最低执行时间的进程进行执行。这也就意味着执行越久,执行优先级越低。
2024-05-12 09:14:41
805
原创 golang testing使用
汇报自定义度量值如果度量值是每次迭代的,你应该将其除以b.N。按照惯例,单位应该以 “/op” 结尾。会覆盖同一单位的任何先前报告的值。如果单位是空字符串,或者单位包含任何空格,会引发 panic。如果单位是基准测试框架本身通常报告的单位(如 “allocs/op”),会覆盖该度量值。将 “ns/op” 设置为 0 将禁止该内置度量值。for i := 0;i < b.N;
2024-05-07 21:15:00
1120
原创 golang netpoller揭秘
netpoller依托于go调度器,提供了一种看上去同步的异步网络编程模式,显著地降低了开发难度更重要的是,go主动挂起goroutine等待网络IO的完成,而不是被动让系统线程去挂起,这就将执行网络IO的goroutine掌控在Go运行时中。
2024-04-28 22:30:00
768
1
原创 golang sync pool
sync.Pool是内置对象池技术,可用于缓存临时对象,避免因频繁建立临时对象所带来的消耗以及对GC造成的压力在很多知名框架中都可以看到sync.Pool的大量使用。比如Gin中用sync.Pool来复用每个请求都会创建的对象但是值得注意的是sync.Pool缓存的对象可能被无通知的清理。
2024-04-25 15:04:37
1107
1
原创 VLL: a lock manager redesign for main memory database systems阅读
VLL锁管理结构由储存到每个原始数据的的未完成锁写请求数量CX和未完成锁读请求数量CS中心事务请求全局队列TxnQueue组成。
2024-04-12 18:20:06
541
原创 KMP算法理解
之所以储存下一个的原因在于,在进行匹配时,模式串要跳到上一个匹配成功的位置,而字符串本身不会移动,那么在这种情况下,当前字符串要匹配的就是已经匹配成功字符的下一个位置。比如对于字符串"abab",其前缀有a、ab、aba,后缀有b、ab、bab,显然最长公共前后缀就是ab。next[i]储存了在以i为开头的后缀,和以j为结尾的前缀匹配时,j的下一个位置。正如next名字所暗示的,下一个,而不是匹配的j本身。在获取到next数组之后,就直接获取到了如果不匹配情况下,模式串该如何走。
2024-03-26 18:13:29
294
原创 如何实时计算数据流中位数
创建一个最小堆和最大堆,其中最小堆的最小值比最大堆的最大值还大,并使最小堆最大堆数量保持均衡,那么中位数边取乎于最小最大堆堆顶。最容易想到的思路就是直接将所有数据进行排序,然后取排序之后的中位数。不过具体的排序思路也有几种。
2024-03-18 11:42:44
492
原创 Mysql 数据如何储存?
我们知道varchar类型的列最多允许65535字节,在允许NULL的情况下最多储存65532字节,因为NULL标识符占1字节,真实长度数量占2字节。此外,65532这个限制是所有varchar列的长度总和,也就是如果存在多个varchar字段,虽然单个没有超出限制,但这多个字段如果合起来超出了限制,那还是会无法创建的。之所以是记录到下条真实数据的偏移量,而不是下条数据偏移量的原因在于可以利用局部性将前面数据的逆序储存的字段长度、NULL值列表缓存起来,减少数据再次查询硬盘次数。
2024-03-18 11:40:35
1968
原创 PacificA: Replication in Log-Based Distributed Storage Systems阅读
PacificA是微软实现的强一致性的分布式共识协议,用于局域网中基于log的大规模储存系统遵循以下原则有以下前提条件系统仅发生fail-stop错误fail-stop是系统组件仅停止运行,而没有其他额外的错误行为消息可能丢弃或者重排,但不会被修改网络分区也可能发生不同服务器上的时钟不一定同步,甚至不一定是松散同步的,但是时间漂移有上限。
2024-02-23 18:50:39
968
原创 kafka 生产者消费者设计思考
如果采用消费者ack的模式,也就是消费者消费完成之后发送确定消息,那么如果消费者在发送ack的时候也失败了,这就会导致重复消费问题。很可惜,kafka最多只能支撑生产者不发送重复的消息,如果是上述场景中消费者没有ack成功导致的重复消费,还是要进行额外幂等处理的。如果broker在发送消息后,立刻认为消息已经被消费了,那么在传输未到达等原因引发的消费未处理情况会使得这样的认为并不正确。为了避免这些问题,kafka将消息划分到有序的分区中,那么只要记录每个分区被每个消费者组消费数据即可。
2024-02-22 15:08:00
755
原创 文档协作技术——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
1183
1
原创 algo-桶排序
桶排序是一种分布排序,将元素数组分到多个桶内,然后每个桶再分别进行排序。其计算复杂度取决于对桶内排序所用算法、使用桶数量以及输入均匀度。主要流程如下。
2024-02-04 18:05:04
972
原创 golang sudog是什么?
sudog代表在等待队列中的goroutine,比如channel发送接受。由于goroutine和同步对象的关系是多对多,因此需要sudog映射。
2024-02-02 15:34:03
1142
原创 为什么golang不支持可重入锁呢?
而其他需要用到的场景,可以通过参数控制是否加锁、或者将递归调用函数提取到新函数中交予新函数加锁、或者采用channel之类的来迂回达成可重入锁的目的。那么在实际开发工程中就可能存在虽然是同一个goroutine运行,但是在一个方法内很难知道其他方法是否也用了这个锁,用来做什么。那么重入锁在此时便无法保证保护不变量。比如说存在两个接口方法A、B,A中调用了B,但是由于这两个方法都可能被其他方法所调用,所以如果没有可重入锁便可能会死锁。在工程中使用锁的原因在于为了保护不变量,也可以用于保护内、外部的不变量。
2024-02-01 18:22:24
1242
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人