好代码实践:基于Redis的轻量级分布式均衡消费队列

本文涉及的产品
云数据库 Redis 版,标准版 2GB
推荐场景:
搭建游戏排行榜
云原生内存数据库 Tair,内存型 2GB
日志服务 SLS,月写入数据量 50GB 1个月
简介: 好代码,给人第一个印象的感觉,就像一篇好文章一样,读起来朗朗上口。不同的文章有不同的风格体裁,不同的代码也有不同的编程风格要求。Python有严格的缩进,像诗歌一样工整对仗;C语言面向过程像散文一样形散神聚,意境深邃;Java语言面向对象又像是写小说一样,能勾勒出一个一个人物形象。但是无论哪一种文章体裁,他的可读性和可理解性都非常重要,只有文章是可读的可理解的,才会吸引更多的读者去读它,让他流传下去,代码也一样,它的可维护性和可读性也非常重要,保证代码可用性,提高代码的简洁程度和可维护程度,才能让我们的代码在计算机上跑的更远,更久。

image.png


作者 | 玄翰
来源 | 阿里技术公众号

一 我对好代码的看法

1 什么是好代码

如果你读过《设计模式之美》,你可能会觉得玩转各种设计模式,符合设计模式的6大基本原则的代码就是好代码;如果读过《clean code》,你可能会觉得好代码的一个标准——整洁;如果你经常研读spring源码,你可能会觉得精妙的设计、高度的抽象,灵活的配置才是好代码;就像是一本书,一千个读者一千个哈姆雷特,每个人按照自己的认知都会有自己的判断。

2 我认为的好代码

如前文所述,不同的人对好代码的认知标准是不同的,我认为的好代码,也局限于我的认知水平,也许今天我觉得是好代码,随着认知的提升,改天也会有不同的想法;就目前的认知而言,我认为的好代码的一些特点:

可用性

对,你没看错,好代码,一定是可用的,可以work的,如果一段代码只是看着好看,用了各种花里胡哨的编码技巧、手法,但是不能work,那就失去了它存在的意义了。所以,好代码,最最最重要的一个特点就是可用性。

可读性

我认为好代码的第二个特点就是可读性,我们的写代码的目标用户有两类,第一类是给编译器看的;第二类是给维护它的程序员看的。针对第一类用户,只要你符合它的语法规范,它就认识,它就可以执行;而第二类用户,就是后期不断的维护它、升级它的程序员同学,如果这段代码,维护它的人都读不懂,那他的长期存在的意义也就不大了。

其他优秀的特点

可维护性、可扩展性、可复用性、强鲁棒性、可测试性等。

好代码的其他优秀特点太多了,不一一列举了。

3 让code在计算机上起舞

回到根源,我们写代码的是干嘛?为的是把我们的所思所想通过计算机认识的指令告诉它,让它来替我们做我们想做的事情。好代码,不仅可以简单的完成我们所思所想,更能够快速、高效、完备的执行。让我们的code一起在计算机上起舞吧。

二 我们为什么要做

2020年五一期间,当大家都在享受五一假期的快乐时光时,我们突然收到hbase报警,整个hbase的IO压力已经接近瓶颈,直接影响数据读写,临时扩容hbase才勉强支撑过去。按照这个发展趋势,一旦遇到业务高峰时,hbase的读写直接会给整个业务链路带来瓶颈问题。为了能够解决海量巴枪数据实时写入hbase+solr时产生的高IO压力,我们设计出一款基于redis实现的轻量级分布式均衡消费队列,实现巴枪数据按照一定规则进行sharding到不同的队列中,实现批量数据攒批去重,然后按批写入hbase+solr,从而降低hbase+solr的IO压力。

三 我们怎么做的

组件整体设计思路:

image.png

整个组件主要分为三大核心模块,master(主节点)、writer(数据写入节点)、worker(工作节点)。

设计机制:弱中心机制,任何一个配置好的节点都可能成为master(主节点)、writer(数据写入节点)、worker(工作节点),具备高可用能力,不存在单机单点瓶颈问题。

master(主节点)职责:

  • 负责实时探活worker(工作节点)是否有变化,掉线情况;
  • 负责分配任务队列到存活的worker(工作节点);
  • 负责实时检测整个redis队列的负载情况。

writer(数据写入节点)职责:

  • 负责分配实时写入任务sharding到不同的队列;
  • 负责检测当前写入队列的负载情况。

worker(工作节点)职责:

  • 负责实时汇报当前worker(工作节点)的状态,保持心跳;
  • 负责定时消费该worker(工作节点)负责的数据。
伟大的linux大神曾说过,"Talk is cheap,让我看看代码"。

四 我们做了什么

1 整个组件的包结构图

image.png

2 简洁的代码结构

image.png

  • 清晰的注释,介绍类的作用和职责
  • 启动项配置,灵活的配置,控制模块是否启动。
  • lambda-logger/lambda表达式,通过简洁语法结构,轻量化代码冗余,提高代码简洁度。
  • 断言判断,替换传统的if-else判断,提高代码的可读性。

整个工程一共60个类,核心代码共1623行, 平均每个类的代码行数为27.05行,最大的一个类代码行数不超过200行。

3 强大的扩展性

image.png

通过钩子回调方式的设计,方便接入的用户能够快速的注入自己的回调实现方法,进行快速扩展业务能力。

4 线上日志展示截图

日志文件

image.png

image.png

master队列分配日志

image.png

worker数据消费日志

image.png

writer队列负载检测日志

image.png

redis消费队列监控大盘

image.png

五 我们的收益

组件部署上线之时,hbase服务端监控指标变化,实现hbase整体使用水位接近50%的优化。

hbase IOPS使用监控

image.png

hbase CPU使用监控

image.png

六 我们的展望

  • 独立抽象组件,基于Redis的轻量级分布式均衡消费队列,是一个全自主创新研发出来的,高可用,可扩展的基础组件,目前已经封装成为一个独立的spring-boot-starter,具备高复用性和高扩展性能力。
  • 广阔的使用场景,基于组件灵活的配置,在涉及的分布式任务队列场景时,都可以使用到它,例如任务中心分发等可以做到天然的均衡负载。
  • 拥抱开源,未来希望将组件开源出去。

七 我的一些理解

好代码,给人第一个印象的感觉,就像一篇好文章一样,读起来朗朗上口。不同的文章有不同的风格体裁,不同的代码也有不同的编程风格要求。Python有严格的缩进,像诗歌一样工整对仗;C语言面向过程像散文一样形散神聚,意境深邃;Java语言面向对象又像是写小说一样,能勾勒出一个一个人物形象。但是无论哪一种文章体裁,他的可读性和可理解性都非常重要,只有文章是可读的可理解的,才会吸引更多的读者去读它,让他流传下去,代码也一样,它的可维护性和可读性也非常重要,保证代码可用性,提高代码的简洁程度和可维护程度,才能让我们的代码在计算机上跑的更远,更久。


技术公开课

《使用Redis消息队列完成秒杀过期订单处理》

本课程共15课时,通过一个Redis的实战案例,介绍Redis消息队列,以及如何在Java程序中监听Redis队列消息,最后结合Redis的key失效机制和消息队列完成对过期订单的处理。

点击https://developer.aliyun.com/learning/course/729?utm_content=g_1000262528开始学习吧~

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
9天前
|
缓存 NoSQL Java
SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解分布式情况下如何添加分布式锁 【续篇】
这篇文章是关于如何在SpringBoot应用中整合Redis并处理分布式场景下的缓存问题,包括缓存穿透、缓存雪崩和缓存击穿。文章详细讨论了在分布式情况下如何添加分布式锁来解决缓存击穿问题,提供了加锁和解锁的实现过程,并展示了使用JMeter进行压力测试来验证锁机制有效性的方法。
SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解分布式情况下如何添加分布式锁 【续篇】
|
1天前
|
NoSQL Redis
基于Redis的高可用分布式锁——RedLock
这篇文章介绍了基于Redis的高可用分布式锁RedLock的概念、工作流程、获取和释放锁的方法,以及RedLock相比单机锁在高可用性上的优势,同时指出了其在某些特殊场景下的不足,并提到了ZooKeeper作为另一种实现分布式锁的方案。
基于Redis的高可用分布式锁——RedLock
|
9天前
|
缓存 NoSQL Java
SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解、如何添加锁解决缓存击穿问题?分布式情况下如何添加分布式锁
这篇文章介绍了如何在SpringBoot项目中整合Redis,并探讨了缓存穿透、缓存雪崩和缓存击穿的问题以及解决方法。文章还提供了解决缓存击穿问题的加锁示例代码,包括存在问题和问题解决后的版本,并指出了本地锁在分布式情况下的局限性,引出了分布式锁的概念。
SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解、如何添加锁解决缓存击穿问题?分布式情况下如何添加分布式锁
|
9天前
|
NoSQL 安全 Java
nicelock--一个注解即可使用Redis分布式锁!
Nicelock的引入为分布式系统中的资源同步访问提供了一个简单高效和可靠的解决方案。通过注解的方式,简化了锁的实现和使用,使开发人员可以将更多精力专注于业务逻辑的实现,而不是锁的管理。此外,Nicelock在保持简单易用的同时,也提供了足够的灵活性和可靠性,满足了不同应用场景下对分布式锁的需求。
22 1
|
1天前
|
NoSQL Go Redis
用 Go + Redis 实现分布式锁
用 Go + Redis 实现分布式锁
|
1月前
|
NoSQL Java Redis
实现基于Redis的分布式锁机制
实现基于Redis的分布式锁机制
|
1月前
|
存储 缓存 NoSQL
Redis常见面试题(二):redis分布式锁、redisson、主从一致性、Redlock红锁;Redis集群、主从复制,哨兵模式,分片集群;Redis为什么这么快,I/O多路复用模型
redis分布式锁、redisson、可重入、主从一致性、WatchDog、Redlock红锁、zookeeper;Redis集群、主从复制,全量同步、增量同步;哨兵,分片集群,Redis为什么这么快,I/O多路复用模型——用户空间和内核空间、阻塞IO、非阻塞IO、IO多路复用,Redis网络模型
Redis常见面试题(二):redis分布式锁、redisson、主从一致性、Redlock红锁;Redis集群、主从复制,哨兵模式,分片集群;Redis为什么这么快,I/O多路复用模型
|
1月前
|
NoSQL Java Redis
分布式锁实现原理问题之使用Redis的setNx命令来实现分布式锁问题如何解决
分布式锁实现原理问题之使用Redis的setNx命令来实现分布式锁问题如何解决
|
1月前
|
canal 缓存 NoSQL
Redis常见面试题(一):Redis使用场景,缓存、分布式锁;缓存穿透、缓存击穿、缓存雪崩;双写一致,Canal,Redis持久化,数据过期策略,数据淘汰策略
Redis使用场景,缓存、分布式锁;缓存穿透、缓存击穿、缓存雪崩;先删除缓存还是先修改数据库,双写一致,Canal,Redis持久化,数据过期策略,数据淘汰策略
Redis常见面试题(一):Redis使用场景,缓存、分布式锁;缓存穿透、缓存击穿、缓存雪崩;双写一致,Canal,Redis持久化,数据过期策略,数据淘汰策略
|
26天前
|
缓存 NoSQL 关系型数据库
(八)漫谈分布式之缓存篇:唠唠老生常谈的MySQL与Redis数据一致性问题!
本文来聊一个跟实际工作挂钩的老生常谈的问题:分布式系统中的缓存一致性。
91 10