• 使用拦截器统一处理通用检查

    繁琐的检查

    在平时的业务开发中,相信大家都有很多这样的代码:

    public void login(Parameter parameter) {
      if (!validateXXX(parameter)) {
        throw new BizException(ErrCode.PAMRM_ERROR);
      }
      
      // 真正的逻辑代码
    }
    

    那么,如果代码还有其他通用的校验,而且每加一个接口都要加这些校验逻辑,久而久之,代码会显得较臃肿,看起来会有很多重复的代码,那么有没有办法精简这部分代码呢?有!

    Read more...
  • [总结]MIT-6.824分布式课程-Mapduce实验

    MIT 6.824分布式系统课程,是一门著名的讲解分布式系统设计原理的课程。通过课程讲解和实验结合来学习分布式系统设计原理,实验和课程安排见课程表

    前言

    我为什么要学习这个课程?之所以会接触到这门课程,是之前在表示对分布式系统感兴趣时一位基友介绍的,由于种种原因并没有开始学。直到最近,开始研究分布式缓存系统的设计才重新开始。有读过笔者之前的文章可能知道,笔者对redis的研究内容比较感兴趣,后面对redis如何做分布式缓存比较感兴趣,于是开始查资料,后来发现etcd在这方面也很强,在学习etcd过程中又了解到了到了raft协议,接着就查到了这门课程中有介绍Raft协议的论文以及相关的实验,刚好得知2020年春季的课程有官方版的视频且被热心网友分享到B站了,再加上完成实验需要用go语言来实现,基于学习分布式系统设计原理和实践go语言的目的,于是就开始学习这门课程。

    实际上,etcd和redis是完全不一样概念的东西,etcd主要用于分布式锁以及集群核心配置,核心特性是高可用;而Redis是内存型数据库,目的是做分布式缓存,保存数据。

    Read more...
  • 聊聊服务灾备

    2018年,有半年的时间在做服务灾备,由于当时对这一块的知识掌握得比较零碎,直接上手实践,没有较系统地学习,在后续的工作中,通过不断实践+学习补充这一块的知识,以及反思当时的实践,逐渐明白了要做灾备的原因和这么做的理由。在此写下自己的小小总结。

    为什么要做灾备?

    当时开始要做灾备的原因,是因为有一次机房A故障了,当时大部分的服务都不可以用:时长上涨、接口失败,原因是:

    1、很多服务都部署到A机房了,导致大部分服务不可用

    2、服务依赖的数据服务(MySQL、Redis)是单点

    出现的问题表现是:时长上涨和接口失败,导致了页面不可用、服务受损。

    这个问题的根本原因是出现服务单点的情况,没有备用的服务可以切换,导致请求/服务上游一直等待,等待一定时间后,就失败了。

    知道问题的根本原因后,解决问题的核心方向就是解决单点问题,解决单点问题的方案有:服务冗余(多一份可用的服务),做灾备。

    Read more...
  • 理解Redis的内存回收机制

    之前看到过一道面试题:Redis的过期策略都有哪些?内存淘汰机制都有哪些?手写一下LRU代码实现?笔者结合在工作上遇到的问题学习分析,希望看完这篇文章能对大家有所帮助。

    从一次不可描述的故障说起

    问题描述:一个依赖于定时器任务的生成的接口列表数据,时而有,时而没有。

    怀疑是Redis过期删除策略

    排查过程长,因为手动执行定时器,set数据没有报错,但是set数据之后不生效。

    set没报错,但是set完再查的情况下没数据,开始怀疑Redis的过期删除策略(准确来说应该是Redis的内存回收机制中的数据淘汰策略触发内存上限淘汰数据。),导致新加入Redis的数据都被丢弃了。最终发现故障的原因是因为配置错了,导致数据写错地方,并不是Redis的内存回收机制引起。

    Read more...
  • 从不可描述的服务雪崩到初探Hystrix

    什么是服务雪崩?什么是服务保护?服务保护的措施有哪些?熔断怎么做?限流怎么做?服务隔离怎么做?降级怎么做?

    真实案例

    举一个自己遇到的真实的例子。 接口A依赖了服务B,接口A的部署情况是有两个机房部署,服务B的部署情况也是两个机房部署。用户请求接口失败会重试,部署架构图如下:

    服务部署架构

    Read more...
  • 聊聊Hystrix中的命令模式

    最近在实践服务熔断时用到了Hystrix这个框架,觉得里面的设计思想挺值得学习,决定深入研究一番。在学习过程中,发现很多名词还是不太熟悉,还是需要有一些技术准备才能继续深入,第一个遇到的是设计模式中的命令模式,命令模式这个设计模式之前也学过,但是由于没有实践机会,所以很快就忘记,现在有机会来实战一次,温故而知新。

    定义

    直接看维基百科上的定义,Command Pattern(命令模式)

    在面对对象编程中,命令模式是一种行为模式,其中对象用于封装执行动作或稍后触发事件所需的所有信息。这些信息包括方法名称,拥有该方法的对象以及方法参数的值。(来自维基百科)

    看概念直接解释名词还是比较模糊,先来看看一个具体的实例,然后再继续解释其中的名词模式的定义。

    Read more...
  • GO语言泛型编程实践

    紧接着上次说到的RDB文件解析功能,数据解析步骤完成后,下一个问题就是如何保存解析出来的数据,Redis有多种数据类型,string、hash、list、zset、set,一开始想到的方案是为每一种数据定义一种数据结构,根据不同的数据类型,将数据保存到不同的数据结构,但是这样的做法带来了比较多的冗余代码,以string和hash为例,一开始的代码是这样的:

    Read more...
  • [从0到1编写服务器]TCP连接建立与断开状态变化

    上篇介绍了socket编程的准备知识,是不是有一种很想马上就开始了解网络编程,甚至开始写点代码的感觉,别着急,网络编程中还有一个比较重要的概念是TCP/IP,中文名称叫网络传输协议,本质上,TCP/IP是一种协议,同时也是网络编程中最重要的协议之一。TCP/IP涉及到的内容实在太多,无奈笔者才疏学浅,无法把整个TCP/IP介绍给大家,这篇文章的目的主要是基于上一篇文章的前提下,介绍TCP连接三次握手和断开连接四次挥手究竟做了什么?socket的状态有哪些?在各个API执行的过程中,socket的状态是怎么变化的?希望通过这篇文章,能让大家对在TCP连接建立与断开过程中,socket的整个状态变化流程有更深入的了解。

    几个术语

    SYN : 同步序列编号,Synchronize Sequence Numbers,仅在三次握手建立TCP连接时有效。表示一个新的TCP连接请求。

    ACK : 确认编号,Acknowledgement Number,对TCP请求的确认标志,同时提示对端系统已经成功接收所有数据。

    FIN : 结束标志,FINISH,用来结束一个TCP会话,但对应端口仍处于开放状态,准备接收后续数据。

    Read more...
  • [从0到1编写服务器]准备知识

    前言

    在互联网发达的时代里,我们的开发过程中,很多场景几乎都需要跟网络打交道,数据库连接、redis连接、nginx转发、RPC服务等等,这个服务器软件的底层实现本质都是网络编程,这也是为什么很多公司在面试的时候都会问到计算机网络。诚然,在正常开发的过程下,几乎不会去自己编写一个完整的服务器,但是,在开发中理解一些概念性的知识却非常有用,甚至在排查一下稀奇古怪的网络错误的时候,TCP/IP协议可以发挥巨大的用处。如果在排查奇怪的问题时,你把学到的网络知识发挥了用途,那么你在公司的前景就不用多说了,而且,作为一个有追求的程序员,不能仅仅满足于业务开发,底层的计算机原理也要经常巩固。毕竟基础知识真的非常重要。

    Read more...
  • [深入理解Redis]读取RDB文件

    最近在做一个解析rdb文件的功能,途中遇到了一些问题,也解决了一些问题。具体为什么要做这件事情之后再详谈,本次主要想聊聊遇到的开始处理文件时遇到的第一个难题:理解RDB文件的协议、如何读取二进制文件。

    RDB文件

    [Redis源码阅读]redis持久化 文章介绍过,Redis的持久化是通过RDB和AOF实现的。Redis的RDB文件是二进制格式的文件,从这个方面再次体现了Redis是基于内存的缓存数据库,不管对于存储到硬盘还是恢复数据都十分快捷。Redis有多种数据类型:string、list、hash、set、zset,不同数据类型占用的内存大小是不一样的,解析出自然语言可以识别的数据就需要使用不同的方法,保存到文件的时候也需要一些协议或者规则。这有点类似于编程语言里面的数据类型,不同的数据类型占用的字节大小不一致,但是保存到计算机都是二进制的编码,就看是读取多少个字节,以怎样的方式解读。

    Read more...