因为笔者既做业务开发,也做基础架构,现在也尝试做大数据方面的东西,所以接触到的中间件比较多。这个专栏会分享一下笔者用过的中间件的使用经验和生产实战相关的知识。目前主要包括:

  • Redis
  • RabbitMQ
  • MySQL
  • Canal

后续应该会分享:

  • Kafka
  • Flink

等等。

前提

Canal上一个正式版是于2019-9-2发布的v1.1.4,笔者几个月前把这个版本的Canal推上了生产环境,部署了HA集群。过程中虽然遇到不少的坑,但是在不出问题的前提下,Canal的作用还是非常明显的。上周的一次改造上线之后,去掉了原来对业务系统订单数据通过RabbitMQ实时推送的依赖,下游的统计服务完全通过上游业务主库的binlog事件进行聚合,从而实现了核心业务和实时统计两个不同的模块解耦。

这篇文章简单分析一下如何搭建生产环境下可靠的Canal高可用集群。

阅读全文

前提

在忍耐了很久之后,忍不住爆发了,在掘金发了条沸点(下班时发的):

这是一个令人悲伤的故事,这条情感爆发的沸点好像被屏蔽了,另外小水渠(Canal意为水道、管道)上线一段时间,不出坑的时候风平浪静,一旦出坑令人想屎。重点吐槽几点:

  • 目前最新的RELEASE版本为v1.1.4,发布于2019-9-2,快一年没更新了。
  • Issue里面堆积了十分多未处理或者没有回应的问题,有不少问题的年纪比较大。
  • master分支经常提交异常的代码,构建不友好,因为v1.1.4比较多问题,也曾经想过用master代码手动构建,导入项目之后决定放弃,谁试试谁知道,可以尝试对比导入和构建MyBatis的源码。

这些都只是表象,下面聊聊踩过的坑。

阅读全文

前提

近段时间,业务系统架构基本完备,数据层面的建设比较薄弱,因为笔者目前工作重心在于搭建一个小型的数据平台。优先级比较高的一个任务就是需要近实时同步业务系统的数据(包括保存、更新或者软删除)到一个另一个数据源,持久化之前需要清洗数据并且构建一个相对合理的便于后续业务数据统计、标签系统构建等扩展功能的数据模型。基于当前团队的资源和能力,优先调研了Alibaba开源中间件Canal的使用。

这篇文章简单介绍一下如何快速地搭建一套Canal相关的组件。

阅读全文

前提

未来一段时间开发的项目或者需求会大量使用到Redis,趁着这段时间业务并不太繁忙,抽点时间预习和复习Redis的相关内容。刚好看到博客下面的UVPV统计,想到了最近看书里面提到的HyperLogLog数据类型,于是花点时间分析一下它的使用方式和使用场景(暂时不探究HyperLogLog的实现原理)。RedisHyperLogLog数据类型是Redid 2.8.9引入的,使用的时候确保Redis版本>= 2.8.9

阅读全文

前提

最近忙于业务开发、交接和游戏,加上碰上了不定时出现的犹豫期和困惑期,荒废学业了一段时间。天冷了,要重新拾起开始下阶段的学习了。之前接触到的一些数据搜索项目,涉及到请求模拟,基于反爬需要使用随机的User Agent,于是使用Redis实现了一个十分简易的UA池。

阅读全文

前提

最近学习Netty的时候想做一个基于Redis服务协议的编码解码模块,过程中顺便阅读了Redis服务序列化协议RESP,结合自己的理解对文档进行了翻译并且简单实现了RESP基于Java语言的解析。编写本文的使用使用的JDK版本为[8+]

阅读全文

前提

Redis5.x之后,单机、哨兵、集群搭建的难度已经简化。鉴于目前看到太多文章都是复制粘贴以往一些3.x版本的一些内容,所以打算基于当前Redis的最新版本做一次单机、哨兵和集群的搭建,记录一下过程步骤和遇到的问题。编写本文的时间是2019年10月6日(国庆假期…),当前Redis的最新版本为5.0.5。操作系统用的是虚拟机里面安装的CentOS 7。先确定已经安装好Redis服务,可以参考笔者写的前一篇文章:《Redis5.x单机服务搭建手记》。出于书写习惯,本文有可能把哨兵称为SentinelRedis Sentinel、哨兵或者Redis哨兵,这四个名词是等价的。

阅读全文

Redis5.x之后,单机、哨兵、集群搭建的难度已经简化。鉴于目前看到太多文章都是复制粘贴以往一些3.x版本的一些内容,所以打算基于当前Redis的最新版本做一次单机、哨兵和集群的搭建,记录一下过程步骤和遇到的问题。编写本文的时间是2019年10月5日(国庆假期…),当前Redis的最新版本为5.0.5。操作系统用的是虚拟机里面安装的CentOS 7

阅读全文

前提

Lettuce是一个RedisJava驱动包,初识她的时候是使用RedisTemplate的时候遇到点问题Debug到底层的一些源码,发现spring-data-redis的驱动包在某个版本之后替换为LettuceLettuce翻译为生菜,没错,就是吃的那种生菜,所以它的Logo长这样:

m-r-c-l-1

既然能被Spring生态所认可,Lettuce想必有过人之处,于是笔者花时间阅读她的官方文档,整理测试示例,写下这篇文章。编写本文时所使用的版本为Lettuce 5.1.8.RELEASESpringBoot 2.1.8.RELEASEJDK [8,11]超长警告:这篇文章断断续续花了两周完成,超过4万字…

阅读全文

前提

最近在跟进一个比较老的系统的时候,发现了所有调度任务使用了spring-context里面的@Scheduled注解和自行基于Redis封装的简易分布式锁控制任务不并发执行。为了不引入其他框架的情况下做一些简单优化,笔者花点时间去研读了一下RedisSET命令的相关文档。

阅读全文

前提

笔者最近在做一个项目时候使用Redis存放客户端展示的订单列表,列表需要进行分页。由于笔者先前对Redis的各种数据类型的使用场景并不是十分熟悉,于是先入为主地看到Hash类型:

USER_ID:1
   ORDER_ID:ORDER_XX: {"amount": "100","orderId":"ORDER_XX"}
   ORDER_ID:ORDER_YY: {"amount": "200","orderId":"ORDER_YY"}

感觉Hash类型完全满足需求实现的场景。然后想当然地考虑使用HSCAN命令进行分页,引发了后面遇到的问题。

阅读全文

前提

Hystrix在2018年11月20日之后已经停止维护,最后一个提交记录是:Latest commit 3cb2158 on 20 Nov 2018,最后一个正式版本为1.5.18。鉴于目前所在公司的技术栈是Spring Cloud,熔断和降级组件主要用的还是Hystrix,这里就Hystrix的完整列表做一个分析记录,方便以后可以随时查询。本文主要参考:Hystrix Configuration。其中,命令配置是针对HystrixCommand,主要包括命令执行(execution)配置、命令降级(fallback)配置、熔断器(circuit breaker)配置、度量统计(metrics)配置和请求上下文配置。

阅读全文

前提

笔者负责的一个系统最近有新功能上线后突然在预警模块不定时报出MySQL死锁导致事务回滚。幸亏,上游系统采用了异步推送和同步查询结合的方式,感知到推送失败及时进行了补偿。于是,笔者争取了一点时间详细分析了导致死锁的多个事务的执行时序,分析并且得出解决方案。

阅读全文

介绍

cron表达式是一个已经存在了很长时间的UNIX工具,因此它的调度功能非常强大且已经经过验证。CronTrigger类的功能是基于cron的调度功能实现的。

CronTrigger使用"cron表达式",可以创建诸如“每周一至周五上午8:00”或“每月最后一个星期五上午1:30”的触发调度时间表(调度计划)。

cron表达式很强大,但是它使用起来也有可能相当混乱(这里大概的意思是说cron的用法相对复杂,容易出错)。本教程旨在解决创建cron表达式的一些谜题,为用户提供一个资源,让他们可以在论坛或邮件列表中提问之前访问这个教程(减少在论坛或者邮件中的提问)。

阅读全文

CronTrigger通常比SimpleTrigger更有用,如果你需要一个基于类似日历的概念重复出现的工作调度计划,而不是SimpleTrigger的精确指定时间间隔。使用CronTrigger,你可以指定任务触发的时间表,例如“每周五中午”或“每个工作日和上午9:30”,甚至“每周一至周五上午9:00至10点之间每5分钟”和1月份的星期五”。即使如此,和SimpleTrigger一样,CronTrigger有一个startTime,它指定何时生效,以及一个(可选的)endTime,用于指定何时停止任务调度。

阅读全文

SimpleTrigger可以满足的调度需求是:在具体的时间点执行一次,或者在具体的时间点执行并且以指定的间隔重复执行若干次(其实永远重复也可以)。比如,你有一个Trigger,你可以设置它在2015年1月13日的上午11:23:54准时触发,或者在当前这个时间点触发,并且每隔2秒触发一次,一共重复5次。

阅读全文

内容

在使用此调度器(Scheduler)之前,它需要被实例化(谁猜到这一点了? <-- 这里估计是官方的调皮)。为了实例化调度器,你需要用到SchedulerFactory。一些Quartz的使用者可能会在JNDI存储中保留SchedulerFactory的实例,其他使用者可能会觉得直接初始化会更加简单(例如下面的示例)。

阅读全文

Quartz API

下面是Quartz API中的关键接口:

  • Scheduler:与调度器交互的主要API(实际上这个就是调度器)。
  • Job:org.quartz.Job,希望由调度器执行的组件,是一个接口,也就是我们使用的时候被调度的任务需要实现此接口。
  • JobDetail:org.quartz.JobDetail,调度任务详情,用于定义调度任务。
  • Trigger:org.quartz.Trigger,也就是触发器,它是一个定义了给定调度任务将被执行的时间表的组件。
  • JobBuilder:org.quartz.JobBuilder,用于定义或者构建JobDetail实例。
  • TriggerBuilder:org.quartz.TriggerBuilder,用于定义或者构建Trigger实例。
阅读全文

Quartz官方文档翻译

2018年5月的时候,因为要理解Quartz的相关东西,当时翻阅过它的文档顺便把它翻译了出来,已经忘记了这个事,好在存档还在硬盘上。其中有部分章节为了节省时间使用了机翻然后人工润色,目前阅读起来应该没有障碍。

这段时间太忙(996,快ICU了),先对基础教程部分重新排版和二次润色,剩下的其他文档有空再补一下。

术语:

  • Scheduler:调度器。
  • SchedulerFactory:调度器工厂。
  • Trigger:触发器。
  • Job:(调度)任务或者作业,在Quartz中体现为JobDetail。

在后面的翻译中,因为个人习惯,可能会中英互用,映射关系为:

  • Scheduler === 调度器
  • SchedulerFactory === 调度器工厂
  • Trigger === 触发器
  • Job、JobDetail === (调度)任务
  • fire === 触发
阅读全文

前提

最近在项目中使用了SpringCloud,基于Zuul搭建了一个提供加解密、鉴权等功能的网关服务。鉴于之前没怎么使用过Zuul,于是顺便仔细阅读了它的源码。实际上,Zuul原来提供的功能是很单一的:通过一个统一的Servlet入口(ZuulServlet,或者Filter入口,使用ZuulServletFilter)拦截所有的请求,然后通过内建的com.netflix.zuul.IZuulFilter链对请求做拦截和过滤处理。ZuulFilterjavax.servlet.Filter的原理相似,但是它们本质并不相同。javax.servlet.Filter在Web应用中是独立的组件,ZuulFilterZuulServlet处理请求时候调用的,后面会详细分析。

阅读全文

概要

AMQP-0-9-1中提供了queue.bind方法用于绑定一个队列到一个交换器,然后发送消息的时候,数据流总是先通过交换器(source)最终到达目标队列中(destination)。RabbitMQ实现了扩展,为交换器提供了一个exchange.bind方法用于绑定一个交换器到另一个交换器。交换器之间的绑定和队列与交换器的绑定在语义上是相同的:单向的、使用路由键和多种交换器类型。这一点允许使用者创建更丰富的路由拓扑。exchange.bind方法中的source和destination反映了消息的流向:从源(source)交换器到目标(destination)交换器。

queue.bind方法一样,可以在相同的绑定端点上创建多个不同的交换器绑定,例如:

  • exchange-source -> exchange-destination-1 -> queue-1
  • exchange-source -> exchange-destination-2 -> queue-2
  • exchange-source -> exchange-destination-3 -> queue-3
阅读全文

前提

工作接近3年,一直有使用RabbitMQ作为服务间解耦的中间件,但是一直没有做一系列学习和总结,这里决心做一个系列总结一下RabbitMQ的运维、使用以及生产中遇到的问题等,以便日后直接拿起来使用。整个系列使用的Linux系统为CentOS 7的最新版本CentOS-7-x86_64-Minimal-1804。而RabbitMQ Server使用当前最新的版本3.7.9.RELEASE。

阅读全文