Redis 5.0 重量级特性 Stream 实现源码分析(二)XREAD 消费流程
Redis 5.0 重量级特性 Stream 实现源码分析(一)overview,XADD
kafka在日志处理领域由于其一系列的工具,其他相关服务,基本上算得上是王者,但是缺点也很明显: 难以维护,性能低,需要大量机器,部署复杂,参数众多。
前阵子Redis 5.0 Beta版本发布 , 随之而来的重大特性“Introduction to Redis Streams”, 似乎跟kafka在功能上有很多类似的地方,但也有不少不一样的点。
阅读全文...
nsqlookupd 源码分析(2)- topic通道注册,查询代码分析
上篇文章介绍了一下nsqlookupd 启动服务的简单流程,限于篇幅到这里来写一下nsqlookupd主要的工作:通道注册登记,以及查询服务。
nsqlookupd 有两个主要的功能:
- nsqd来注册所有topic、channel的分布信息,nsqlookupd记录哪些topic在哪些机器上;
- 给消费端来查询对应的topic所在的机器列表,以供订阅消费;
nsqlookupd 源码分析(1)- 启动服务
之前的文章写了nsqd的代码逻辑,这里简单介绍一下作为负载均衡或者消息topic/channel汇总的nsqlookupd 的实现原理。相对来说nsqlookupd 比nsqd简单很多,不需要持久化,不需要太多的携程,也没有那么多channel。因此这里简单介绍一下。
nsqlookupd作为其他nsqd的中心,主要负责topic的等级注册,以及channel的登记注册,topic位置查询等服务。生产者一般可以不用连接nsqlookupd,但是消费者在消费时,如果是分布式环境就得连接nsqlookupd,查询指定topic在哪些机器上,进而连接对应的机器,SUB上去消费内容。这里类似redis的集群方案,只是redis集群是纯分散的,而nsqd则是把这个任务交给了nsqlookupd, 这样有利有弊,设计结构复杂一些,但是nsqlookupd的存在让服务维护容易,并且模块清晰一些。
nsqd 源码分析(5)- 消息的订阅流程
这里记录一下消息的消费者订阅流程,配合上面文章写的消息发送流程。不过这里暂时没讲lookupd的过程,后面在详细介绍。
- 消费者使用TCP协议,发送SUB topic channel 命令订阅到某个channel上,记录其client.Channel = channel,通知c.SubEventChan;
- 消费者启动后台协程protocolV2.messagePump订阅c.SubEventChan 并得知channel有订阅消息;
- 开始订阅管道subChannel.memoryMsgChan/backend, 每个客户端都可以订阅到channel的内存或者磁盘队列里面;
- 待生产者调用第四步后,其中一个client会得到消息:msg := <-memoryMsgChan;
- 客户端记录StartInFlightTimeout的发送中消息队列,进行超时处理;
- SendMessage 将消息+msgid发送给消费者;
- 消费者收到msgid后,发送FIN+msgid通知服务器成功投递消息,可以清空消息了;
nsqd 源码分析(4)- 消息的发送流程
本文从消息发送者的PUB到最后消息被SUB接收,整个流程串起来讲一下nsqd是怎么接收消息的,这部分先写发送流程。
- 生产者PUB topic消息;
- topic.PutMessage 到 topic.memoryMsgChan;
- 每topic消息有后台协程topic.messagePump进行Topic.memoryMsgChan监听;
- topic.messagePump 遍历每个channel调用channel.PutMessage发送消息到channel.memoryMsgChan ;
nsqd 源码分析(3)- Channel实现原理
写一下Channel的实现,比topic相对简单一些,但channel是最接近消费者端的,有他特有的东西,包括投递,确认等;
nsqd的channel的作用在于能对指定的队列topic,进行多份投递,或者说消费,一份队列可以给多个消费者重复消费,有点类似于kafka的consumer_group,每个consumer_group拥有独立的position, 不同group之间可以消费同一份内容的多个副本。
这里稍微做个对比,kafka的已经消费国的消息是可以继续保留的,而nsq则如果消费完了,就会删除掉,也就是没有position可以供回溯,或者重复消费,只要客户端发发送FIN后,消息就会销毁,也不会保留在磁盘上面,这点比kafka简单多了,当然,轻量级消息队列也不太需要这么复杂的功能。
nsqd 源码分析(1)- 启动服务
前段时间了解Go语言,开始了解Go的优秀开源服务,所以找出NSQ学习一下,下载了一份nsq源码开始学习,顺便记录一下阅读的笔记。
对协程实现原理感兴趣的话推荐看一看libtask,几年前在看源码的时候写过2篇笔记,里面有代码和注释:libtask协程库实现源码学习
NSQ是一个实时分布式消息处理服务,支持分布式,其源码包括:
1. nsqd 作为一个主要的消息接受,发送, 跟客户端沟通的后台进程,负责监听客户端连接,处理客户端的发送接收请求;
2. nsqlookupd 是一个管理进程,其他所有nsqd启动会尝试不断连接他,上报topic信息等;
3. nsqadmin 管理进程;
4. 其他便利工具;
让人爱恨交加的Redis Scan遍历操作原理
还记得,深夜,你在Redis 命令行里敲入"keys *" 后,线上开始报警,然后只能举起双手焦急的等待几千万key被慢慢扫描几十分钟还没结果,束手无策的时候,你跟所有redis用户拥有同样的心声:“就不能温柔点让我遍历一遍所有的数据吗?”
要知道,遍历一下数据库里面的所有数据,是多么理所应当的要求,这在mysql等关系型数据库眼里是多么的不可理解的。
Memcached 缓存过期机制源码分析
之前的文章说了 memcached源码学习-线程框架 和 get操作处理代码, 其实最重要的是他的缓存过期策略,以及内存管理机制, 篇幅过长分几篇文章写,这里写一下memcached的缓存过期策略。
说到缓存过期策略,网上有一大堆帖子会介绍说“LRU, 最近最少使用 ” 算法,而且源码中间也是大量的含lru字样的函数,变量,比如lru_crawler_crawl 等,很多人也就信了,可事实却不是这样的。 阅读全文...
memcached LRU过期机制lru_crawler指令可能会错误的清理不应该的slabs的bug
1.4.20 版本在处理 lru_crawler crawl 2 指令的时候,lru_crawler_crawl函数竟然存在变量未定义的bug,从而导致错误的清理了不应该的slabs槽位的数据。
阅读全文...
memcached 简单get操作处理代码学习
好久没写博客了,这里简单记录一下memcached的get操作处理过程,之前写了些memcached的主体流程/线程框架。get命令相对来说是最简单的了, 主要分为这几步: 读取命令; 解析命令;查找key, 拼接返回数据格式;发送结果给客户端;
memcached里面一段神奇,危险,暂且无bug的code: add_iov
翻memcached代码,看到一个函数:add_iov , 在里面着实纳闷了许久,多次认为这个代码会有问题,于是打日志,gdb上去调试,最后不得不承认: 这代码能work!(不过很危险)
memcached源码学习-线程框架
看了看memcached, memcached 主要的线程框架是master-slave的主线程-工作线程模式,单进程,多线程,之间通过管道和链表通信,基本就是这样。
下面具体看下代码。 阅读全文...
Redis Scan迭代器遍历操作原理(二)–dictScan反向二进制迭代器
续上一篇文章 Redis Scan迭代器遍历操作原理(一)--基础 ,这里着重讲一下dictScan函数的原理,其实也就是redis SCAN操作最有价值(也是最难懂的部分)。
关于这个算法的源头,来自于githup这里:Add SCAN command #579,长篇的讨论,确实难懂····建议看看这帖子,antirez 跟pietern 关于这个奇怪算法的讨论···
这个算法的作者是:Pieter Noordhuis,作者称其为:reverse binary iteration ,不知道我一对一翻译为“反向二进制迭代器”可不可以,不过any way ··作者自己也没有明确的证明其真假: 阅读全文...
Redis Scan迭代器遍历操作原理(一)–基础
Redis在2.8.0版本新增了众望所归的scan操作,从此再也不用担心敲入了keys*, 然后举起双手看着键盘等待漫长的系统卡死了···
命令的官方介绍在这里, 中文版由huangz同学细心翻译了,作者Antirez的介绍在这里:Finally Redis collections are iterable (我又邪恶的想到了之前他那次机器down机的事故了···)。
具体的使用参考上面的链接即可,这里大概介绍一下Scan操作的实现原理。 阅读全文...
Redis从库备份和同步时小概率存在较严重数据错乱的Bug
先说一下影响:在主从模式下的从redis如果开启了定期BGSAVE,并且在做SYNC的时候,可能存在数据错乱的问题,目前2.8.8最新稳定版也存在这个bug。
redis的BGSAVE和slaveof触发的同步操作是互不相关的(对于从库),所以就完全有可能同时在进行备份和同步。看一下下面的代码: 阅读全文...
Redis Slave进行数据备份BGSAVE时可能内存突发跑满
前几天突然线上的redis slave 把64G的内存给占用满了,本来机器上的数据正常只会占用55.5%左右35G的内存的。
查看进程情况,当时redis正好在做BGSAVE操作,所以有2个Redis进程存在,初步怀疑是因为这个原因,但是理论上redis的BGSAVE是fork出来的进程,他们刚开始是共用物理内存的(Redis源码学习-AOF数据持久化原理分析(0)),除非主进程有数据修改,其实就是利用了操作系统的COW机制,巧妙的对redis做了一个数据快照。但明显线上系统不可能短时间内触发大部分数据的修改,所以排除这个的原因。 阅读全文...
近期评论