Java日知录

一个坚持原创,有态度的博客!

0%

案例背景

在互联网分布式场景中,原本一个系统被拆分成多个子系统,要想完成一次写入操作,你需要同时协调多个系统,这就带来了分布式事务的问题(分布式事务是指:一次大的操作由多个小操作组成,这些小的操作分布在不同的服务器上,分布式事务需要保证这些小操作要么全部成功,要么全部失败)。那怎么设计才能实现系统之间的事务一致性呢? 这就是咱们今天要讨论的问题,也是面试的高频问题。

这一讲,我先从“解决分布式事务”这个问题本身出发,讲解答题思路和你要掌握的知识点。然后再结合“高并发”场景,看在该场景下如何保证分布式系统事务一致性?希望通过这种方式,让你彻底掌握分布式系统事务一致性的解题思路和技术认知。

以京东旅行系统为例,早期的交易系统是通过 .NET 实现的,所有的交易下单逻辑都写在一个独立的系统中。随着技术改造,我们用 Java 重写了核心系统,原本的系统也被拆分成多个子系统,如商品系统、促销系统、订单系统(为了方便理解,我只拿这三个系统举例)。当用户下单时,订单系统生成订单,商品系统扣减库存,促销系统扣减优惠券,只有当三个系统的事务都提交之后,才认为此次下单成功,否则失败。

阅读全文 »

大家好,我是飘渺。

本文介绍如何在容器环境下配置JVM堆参数大小。

背景信息

当您的业务是使用Java开发,且设置的JVM堆空间过小时,程序会出现系统内存不足OOM(Out of Memory)的问题。特别是在容器环境下,不合理的JVM堆参数设置会导致各种异常现象产生,例如应用堆大小还未到达设置阈值或规格限制,就因为OOM导致重启等。

阅读全文 »

大家好,在上一篇文章中我们详细介绍了在RBAC模型中如何集成数据权限,本篇文章我们将通过实际案例,从代码实战的角度来实现这样的一个数据权限。

在开始阅读本文之前,建议先把上篇文章 读一遍,读一遍,读一遍!
RBAC权限设计中如何整合数据权限?

数据权限模型

上篇文章的数据模型是基于传统的RBAC模型来设计的,由于我们这里的应用场景不一样,所以这里的数据权限模型并没有严格按照上篇文章的方案来设计,但是万变不离其宗,核心原理还是相同的。

首先我来介绍一下我们最终实现的效果

阅读全文 »

电商当项目经验已经非常普遍了,不管你是包装的还是真实的,起码要能讲清楚电商中常见的问题,比如库存的操作怎么防止商品被超卖。

在日常开发中有很多地方都有类似扣减库存的操作,比如电商系统中的商品库存,抽奖系统中的奖品库存等。

解决方案

常见的解决方案有以下三种:

  1. 使用 mysql 数据库,使用一个字段来存储库存,每次扣减库存去更新这个字段。
  2. 还是使用数据库,但是将库存分层多份存到多条记录里面,扣减库存的时候路由一下,这样子增大了并发量,但是还是避免不了大量的去访问数据库来更新库存。
  3. 将库存放到 redis 使用 redis 的 incrby 特性来扣减库存。
阅读全文 »

计算机学什么

抽象模型

庄子说过吾生有崖,知无涯。以有限的生命去学习无尽的知识是很愚蠢的。所以,学习的终极目标一定不是知识本身,因为知识是表象的、不稳定、会过时。那么我们应该学什么,什么东西才是永恒的?也许我们会有很多见解,比如学习哲学,或者叫哲科;或者学习方法论;或者学习抽象模型等等…

这些抽象模型的完美体现就是我们经常看到的数学公式,公式好比万能工具,通过它我们可以知道宇宙和自然是如何规律运转的。

现实中,我们会发现各个学科都有自己的抽象模型,这些模型好比天上的繁星,有相似的,更多的是各不相同。所以,认知结构的拓展其实就是对模型边界的拓展,我们拥有的模型越多,我们的认知越丰富。

对于计算机来说,什么是那个不变的宗呢?

阅读全文 »

大家好,我是飘渺。

今天我们通过一篇文章来认识一下常见消息队列RabbitMQ、RocketMQ、Kafka。

RabbitMQ

RabbitMQ各组件的功能

  • Broker :一个RabbitMQ实例就是一个Broker
  • Virtual Host :虚拟主机。相当于MySQL的DataBase,一个Broker上可以存在多个vhost,vhost之间相互隔离。每个vhost都拥有自己的队列、交换机、绑定和权限机制。vhost必须在连接时指定,默认的vhost是/。
  • Exchange :交换机,用来接收生产者发送的消息并将这些消息路由给服务器中的队列。
  • Queue :消息队列,用来保存消息直到发送给消费者。它是消息的容器。一个消息可投入一个或多个队列。
  • Banding :绑定关系,用于消息队列和交换机之间的关联。通过路由键(Routing Key)将交换机和消息队列关联起来。
  • Channel :管道,一条双向数据流通道。不管是发布消息、订阅队列还是接收消息,这些动作都是通过管道完成。因为对于操作系统来说,建立和销毁TCP都是非常昂贵的开销,所以引入了管道的概念,以复用一条TCP连接。
  • Connection :生产者/消费者 与broker之间的TCP连接。
  • Publisher :消息的生产者。
  • Consumer :消息的消费者。
  • Message :消息,它是由消息头和消息体组成。消息头则包括Routing-KeyPriority(优先级)等。
阅读全文 »

在架构设计中,要实现业务上的复用,一个比较可行的做法是,把各个基础业务封装成共享服务,供上层所有应用调用。所以今天,我就来和你聊一聊,如何
从头开始,落地这样一个典型的共享服务。

我们知道,落地一个微服务其实并不困难,但要实现一个能够高度复用的共享服务并不容易,在落地过程中,经常会有一系列的问题困扰着我们。

  • 我们事先对服务的边界没有进行很好的划分,结果在落地的过程中,大家反复争论具体功能的归属。

  • 由于对业务的了解不够深入,我们要么设计不足,导致同一个服务有很多版本;要么服务过度设计,实现了一堆永远用不上的功能。

阅读全文 »

大家好,我是飘渺。

分布式数据库架构下,索引的设计也需要做调整,否则无法充分发挥分布式架构线性可扩展的优势。今天我们就来聊聊 “在分布式数据库架构下,如何正确的设计索引?”。

主键选择

对主键来说,要保证在所有分片中都唯一,它本质上就是一个全局唯一的索引。如果用大部分同学喜欢的自增作为主键,就会发现存在很大的问题。

因为自增并不能在插入前就获得值,而是要通过填 NULL 值,然后再通过函数 last_insert_id()获得自增的值。所以,如果在每个分片上通过自增去实现主键,可能会出现同样的自增值存在于不同的分片上。

阅读全文 »

大家好,我是飘渺。

上次面试官问了个问题:应用上线后Cpu使用率飙升如何排查?

其实这是个很常见的问题,也非常简单,那既然如此我为什么还要写呢?因为上次回答的时候我忘记将线程PID转换成16进制的命令了。

所以我决定再重温一遍这个问题,当然贴心的我还给大家准备好了测试代码,大家可以实际操作一下,这样下次就不会忘记了。

阅读全文 »

大家好,我是飘渺。

分布式数据库架构下,索引的设计也需要做调整,否则无法充分发挥分布式架构线性可扩展的优势。今天我们就来聊聊 “在分布式数据库架构下,如何正确的设计索引?”。

主键选择

对主键来说,要保证在所有分片中都唯一,它本质上就是一个全局唯一的索引。如果用大部分同学喜欢的自增作为主键,就会发现存在很大的问题。

因为自增并不能在插入前就获得值,而是要通过填 NULL 值,然后再通过函数 last_insert_id()获得自增的值。所以,如果在每个分片上通过自增去实现主键,可能会出现同样的自增值存在于不同的分片上。

比如,对于电商的订单表 orders,其表结构如下(分片键是o_custkey,表的主键是o_orderkey):

阅读全文 »