本文为分布式系列文章的集锦汇总,长期保持置顶及更新,读者可以在本文中更好的学习到某个具体的系列。

注: 转载本博客文章请注明出处,原创不易,洗文可耻。

我说分布式事务系列

文章链接
我说分布式事务之TCC
我说分布式事务之最大努力通知型事务
我说分布式事务之可靠消息最终一致性事务1-原理及实现
我说分布式事务之消息一致性事务2-rocketmq的实现
【汇总】我说分布式事务系列
分布式事务之聊聊TCC
分布式事务最终一致性常用方案
TCC-Transaction源码解析之事务执行
TCC-Transaction源码解析之事务补偿
自己写分布式事务框架之原理篇[详解本地消息表]

跟我学RocketMQ

文章链接
[1-1]安装RocketMQ
[1-2]安装RocketMQ-Console管理平台
[1-3]发送普通消息及封装DefaultMQProducer支持spring
[1-4]消费消息及封装DefaultMQPushConsumer支持spring
[1-5]发送事务消息实现分布式事务及封装TransactionMQProducer支持spring
[2-0]跟我学RocketMQ之消息重试
[2-1]跟我学RocketMQ之消息幂等
[2-2]跟我学RocketMQ之消息轨迹实战与源码分析
[2-3]跟我学RocketMQ之消息发送源码解析
[2-4]跟我学RocketMQ之批量消息发送源码解析
[2-5]跟我学RocketMQ之消息消费源码解析-p1
[2-6]跟我学RocketMQ之消息消费源码解析-p2
[2-7]跟我学RocketMQ之订阅关系一致性源码讨论
[2-8]跟我学RocketMQ之消息拉取源码解析
[2-9]跟我学RocketMQ之开源客户端混合云实践与案例解析
[2-10]跟我学RocketMQ之事务消息发送源码解析
[2-10]跟我学RocketMQ之事务消息存储源码解析
[2-11]跟我学RocektMQ之事务消息提交及回查源码解析
[2-12]跟我学RocketMQ之定时消息源码解析
[2-13]跟我学RocektMQ之理解长轮询机制
[2-14]跟我学RocketMQ之消息持久化原理与Mmap
[2-15]跟我学RocketMQ之拉模式消费的两种方式
[2-16]跟我学RocketMQ之聊聊死信队列

分库分表

文章链接
我说分布式之分库分表
跟我学shardingjdbc之shardingjdbc入门
跟我学shardingjdbc之使用jasypt加密数据库连接密码
跟我学shardingjdbc之分布式主键及其自定义
跟我学shardingjdbc之自定义分库分表策略-复合分片算法自定义实现

Read More

本文将主要记录在日常开发中遇到的各种问题。以技术类别进行章节划分,作为个人的编码备忘录随时进行查阅,并长期进行置顶。

问题排查

CPU异常飙高排查思路

cpu占用高如何排查

  • 查看占用cpu高的进程: 通过 top 命令找到 CPU 消耗最高的进程,并记住进程 ID {pid}。

    top -M -n 2 -d 3 >{pid}/top.txt 查看top

  • 再次通过 top -Hp {pid} 找到 CPU 消耗最高的线程 ID,并记住线程 ID(十进制).
  • 通过 JDK 提供的 jstack 工具 dump 线程堆栈信息到指定文件中。

    jstack {pid} >{pid}/jstack_1.txt 一次堆栈快照 备用

    jstack {pid} >{pid}/jstack_2.txt 两次堆栈快照 备用

  • 由于刚刚的线程 ID 是十进制的,而堆栈信息中的线程 ID 是16进制的,因此我们需要将10进制的转换成16进制的,并用这个线程 ID 在堆栈中查找。

    使用 printf “%x\n” [十进制数字] ,可以将10进制转换成16进制。

  • 通过刚刚转换的16进制数字从堆栈信息里找到对应的线程堆栈。就可以从该堆栈中看出端倪。

  • 通过top查看当前进程cpu占用情况,找到cpu使用最高的进程PID
  • 查看子进程情况

    top -p 4606 -H

  • 将 子进程id 转换成16进制

    printf “%x \n” 4648 结果为1228

  • 使用jstack查询具体出现问题的代码位置

    jstack 4606|grep 1228 -C 30

  • 根据打印结果定位到具体代码位置

JavaCore相关

该模块主要记录JavaCore相关的技术点

bigdecimal四舍五入

BigDecimal.ROUND_HALF_UP: 遇到.5的情况时往上近似,例: 1.5 ->;2
BigDecimal.ROUND_HALF_DOWN : 遇到.5的情况时往下近似,例: 1.5 ->;1

bigDecimal转换为百分比,保留若干小数

DecimalFormat decimalFormat = new DecimalFormat("0.00%");
BigDecimal decimal = new BigDecimal(count.intValue()).divide(new BigDecimal(allCount), 5, ROUND_HALF_UP);
String formatted = decimalFormat.format(sdPercent);

bigDecimal精确度

BigDecimal.setScale(5,  BigDecimal.ROUND_HALF_UP)  -->保留五位小数,最后一位遇到.5的情况时往上近似

Read More

日常开发中,对于遗留系统代码逻辑的改造,通常不会粗暴地采用停机更新方式直接迁移到新业务逻辑,往往需要通过灰度方式逐步迁移到新逻辑,最后再把老业务逻辑下线。

这个过程中就涉及到新老业务逻辑并存的问题,而这个问题是需要研发同学去通过工具、编码、配置等方式实现灰度策略,制定灰度计划,并付诸实施,保障系统能够平稳地从老业务逻辑迁移至新业务逻辑。

通常情况下,如果是http接口灰度,我们可以利用网关的特性,如nginx自身的能力,根据cookie中传递的唯一标识进行百分比分流,通过免开发的方式进行灰度。

但在实际开发中,我们面对的系统不仅仅是网关类系统,大部分情况下,分布式系统开发场景下面对的是RPC类接口或者异步消息逻辑,对于这类型代码逻辑的灰度就需要研发同学通过编码方式,细粒度的进行灰度。

本文中,我们就后者展开代码级别的讨论和分享,向读者介绍笔者在日常开发中,面对接口级别的灰度场景是如何通过编码实现具体的灰度策略的,本文权当抛砖引玉,为读者全景展示​后端研发套路之灰度场景下的瑞士军刀具体是如何使用的。在今后的开发工作中如果你遇到类似场景,可以参考笔者思路,开发适合自己业务的灰度套路。

Read More

在之前的一篇文章 手写JDK组件之阻塞队列BlockedQueue 中 ,我们模仿Java的ArrayBlockingQueue实现了一个阻塞队列。并通过该案例对阻塞队列的实现机制有了一个初步的认识。

实际上,Java中的阻塞队列用处还是比较广泛的,尤其是当我们不需要使用复杂的分布式消息队列,只是想要基于生产者-消费者模型,解耦业务逻辑,那么我们就可以借助内存队列实现。

这类型业务场景往往具备以下特点:

  • 消息发送量不多
  • 消息的安全性不高,可以容忍丢失
  • 不需要保证HA
  • 不需要提供完备的failover机制

举个例子,比如说当订单下单成功后我们想发送一个站内信,通知商户或者用户下单成功,仅仅作为一个提醒。类似这种场景,我们就可以借助内存队列实现。

基于我们刚提出的这个场景,编写一个demo进行验证。

Read More

笔者在两年前写过一篇RestTemplate使用相关的文章,地址: springboot中使用RestTemplate调用web服务小结

文章写作时SpringBoot版本尚在1.x徘徊,随着SpringBoot版本升级,有些用法在2.x版本中已经不适用。恰逢最近又用到了RestTemplate进行HTTP接口对接,
因此写作本文对最新的使用方法进行小结,方便后续参考,也希望能够帮到读者更好的使用RestTemplate在2.x的SpringBoot中进行HTTP接口的调用。

对于Get方式请求,2.x与1.x是兼容的,因此可以直接阅读上文中提到的链接,本文就不再重复赘述。

Read More

本文我们重点讲解一下Stream中收集器Collector的主要使用方式。

收集器

收集器(Collector)的作用为:将流中元素累积成一个结果作用于终端操作collect()上

关于收集器,我们主要关注:

collect()(操作实现Collector接口的集合)、

Collector(接口)

Collectors(工具类)

日常开发中,我们使用最多的是预定义收集器功能(Collectors)

它的作用主要是:

将流元素规约和汇总为一个值

将流元素分组

将流元素分区

Read More

本文是Java8函数式编程的最后一个章节,到此我们的Stream相关的讲解就暂时告一段落。

本文中我将带领读者朋友一起学习一下Stream高级编程相关的知识。

规约与汇总

Stream操作中有两个相对高阶的概念,分别为规约和汇总。

规约(reduce)

将Stream流中元素转换成一个值

汇总(collect)

将Stream流中的元素转换成一个容器,如Map 、List 、 Set

上文我们已经讲过了汇总操作Collect,此处我们重点讲讲规约操作(reduce)

Read More

上文中主要学习了Stream编程中的中间操作,本文我们接着分析终端操作,它分为短路和非短路操作。

我们提前明确一个原则:一个流一旦经过终端操作,就不能进行后续操作了。

allMatch: 检测所有元素是否满足断言,如果都满足返回true,有一个不满足返回false

@Test
public void allMatchTest() {
    boolean isMatch = list.stream()
            // 打印出部门商品名称即结束,参考打印结果
            .peek(sku -> System.out.println(sku.getSkuName()))
            // allMatch是短路操作
            .allMatch(sku -> sku.getTotalPrice() > 100);
    System.out.println(isMatch);
}

运行结果:

无人机
VR一体机
牛仔裤
false

Read More

Fork me on GitHub