Redis数据类型简介

Introduction to Redis data types

Redis支持的所有数据结构列表

  • String: 字符串;
  • List: 根据插入顺序排序的字符串元素集合,基本上是一个双向链表;
  • Set: 不重复且无序的字符串元素的集合;
  • SortedSet: 排序集,类似于Set,但每个字符串元素都与一个浮点数(称为score)相关联,元素总是按score排序,因此与Set不同,可以检索一系列元素(例如,您可能会问:给我前10个,或后10个);
  • Hash: 是由与值关联的字段组成的映射,key 和 value 都是字符串;
  • Bitmap(Bit array): 通过特殊的命令,你可以将 String 值当作一系列 bits 处理:可以设置和清除单独的 bits,数出所有设为 1 的 bits 的数量,找到最前的被设为 1 或 0 的 bit,等等
  • HyperLogLog: 用于估计Set中元素数量的的的概率数据结构;
  • Stream (Redis 5.0+): 一种更抽象的日志数据类型:就像一个日志文件一样,总是以仅追加的方式操作,Redis的stream就是一种append only的数据类型。

Redis key 的大小最大为 512MB

阅读全文 »

记得开始学习Java的时候,一遇到多线程情况就使用synchronized,相对于当时的我们来说synchronized是这么的神奇而又强大,那个时候我们赋予它一个名字“同步”,也成为了我们解决多线程情况的百试不爽的良药。但是,随着学习的进行我们知道在JDK1.5之前synchronized是一个重量级锁,相对于j.u.c.Lock,它会显得那么笨重,以至于我们认为它不是那么的高效而慢慢摒弃它。
不过,随着Javs SE 1.6对synchronized进行的各种优化后,synchronized并不会显得那么重了。下面来一起探索synchronized的基本使用、实现机制、Java是如何对它进行了优化、锁优化机制、锁的存储结构等升级过程。

1 基本使用

Synchronized是Java中解决并发问题的一种最常用的方法,也是最简单的一种方法。Synchronized的作用主要有三个:

  1. 原子性:确保线程互斥的访问同步代码;
  2. 可见性:保证共享变量的修改能够及时可见,其实是通过Java内存模型中的 “对一个变量unlock操作之前,必须要同步到主内存中;如果对一个变量进行lock操作,则将会清空工作内存中此变量的值,在执行引擎使用此变量前,需要重新从主内存中load操作或assign操作初始化变量值” 来保证的;
  3. 有序性:有效解决重排序问题,即 “一个unlock操作先行发生(happen-before)于后面对同一个锁的lock操作”;

从语法上讲,Synchronized可以把任何一个非null对象作为”锁”,在HotSpot JVM实现中,锁有个专门的名字:对象监视器(Object Monitor)
Synchronized总共有三种用法:

阅读全文 »

1. Java7中ConcurrentHashMap

ConcurrentHashMap 和 HashMap 思路是差不多的,但是因为它支持并发操作,所以要复杂一些。
整个 ConcurrentHashMap 由一个个 Segment 组成,Segment 代表”部分“或”一段“的意思,所以很多地方都会将其描述为分段锁。注意,行文中,我很多地方用了“槽”来代表一个 segment。
简单理解就是,ConcurrentHashMap 是一个 Segment 数组,Segment 通过继承 ReentrantLock 来进行加锁,所以每次需要加锁的操作锁住的是一个 segment,这样只要保证每个 Segment 是线程安全的,也就实现了全局的线程安全。

upload successful

concurrencyLevel:并行级别、并发数、Segment 数,怎么翻译不重要,理解它。默认是 16,也就是说 ConcurrentHashMap 有 16 个 Segments,所以理论上,这个时候,最多可以同时支持 16 个线程并发写,只要它们的操作分别分布在不同的 Segment 上。这个值可以在初始化的时候设置为其他值,但是一旦初始化以后,它是不可以扩容的。
再具体到每个 Segment 内部,其实每个 Segment 很像之前介绍的 HashMap,不过它要保证线程安全,所以处理起来要麻烦些。

1.1. 初始化

阅读全文 »

HashMap可能是面试的时候必问的题目了,面试官为什么都偏爱拿这个问应聘者?因为HashMap它的设计结构和原理比较有意思,它既可以考初学者对Java集合的了解又可以深度的发现应聘者的数据结构功底。
阅读前提:本文分析的是源码,所以至少读者要熟悉它们的接口使用,同时,对于并发,读者至少要知道CAS、ReentrantLock、Unsafe操作这几个基本的知识,文中不会对这些知识进行介绍。Java8用到了红黑树,不过本文不会进行展开,感兴趣的读者请自行查找相关资料。

1. Java7中HashMap

HashMap是最简单的,一来我们非常熟悉,二来就是它不支持并发操作,所以源码也非常简单。
首先,我们用下面这张图来介绍HashMap的结构。

upload successful

大方向上,HashMap 里面是一个数组,然后数组中每个元素是一个单向链表。为什么是这种的结构,这涉及到数据结构方面的知识了。

阅读全文 »

背景

分布式事务是企业集成中的一个技术难点,也是每一个分布式系统架构中都会涉及到的一个东西,特别是在微服务架构中,几乎可以说是无法避免。

ACID

指数据库事务正确执行的四个基本要素:

  • 原子性(Atomicity)
  • 一致性(Consistency)
  • 隔离性(Isolation)
  • 持久性(Durability)
阅读全文 »

众所周知,数据库能实现本地事务,也就是在同一个数据库中,你可以允许一组操作要么全都正确执行,要么全都不执行。这里特别强调了本地事务,也就是目前的数据库只能支持同一个数据库中的事务。但现在的系统往往采用微服务架构,业务系统拥有独立的数据库,因此就出现了跨多个数据库的事务需求,这种事务即为“分布式事务”。那么在目前数据库不支持跨库事务的情况下,我们应该如何实现分布式事务呢?本文首先会为大家梳理分布式事务的基本概念和理论基础,然后介绍几种目前常用的分布式事务解决方案。废话不多说,那就开始吧~

什么是事务?

事务由一组操作构成,我们希望这组操作能够全部正确执行,如果这一组操作中的任意一个步骤发生错误,那么就需要回滚之前已经完成的操作。也就是同一个事务中的所有操作,要么全都正确执行,要么全都不要执行。

事务的四大特性 ACID

说到事务,就不得不提一下事务著名的四大特性。

阅读全文 »

前言

循环依赖:就是N个类循环(嵌套)引用。通俗的讲就是N个Bean互相引用对方,最终形成闭环。用一副经典的图示可以表示成这样(A、B、C都代表对象,虚线代表引用关系):
upload successful

注意:其实可以N=1,也就是极限情况的循环依赖:自己依赖自己
另需注意:这里指的循环引用不是方法之间的循环调用,而是对象的相互依赖关系。(方法之间循环调用若有出口也是能够正常work的)

可以设想一下这个场景:如果在日常开发中我们用new对象的方式,若构造函数之间发生这种循环依赖的话,程序会在运行时一直循环调用最终导致内存溢出,示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Main {

public static void main(String[] args) throws Exception {
System.out.println(new A());
}

}

class A {
public A() {
new B();
}
}

class B {
public B() {
new A();
}
}
阅读全文 »

一、根据 Java 进程 ID,用 pstop 命令查询出 CPU 占用率高的线程

1
2
3
4
5
6
7
8
9
10
11
ps -mp <pid> -o THREAD,tid,time | sort -rn | more // (sort -rn 已数值的方式进行逆序排列)
// 或top -Hp <pid>
top - 08:31:16 up 30 min, 0 users, load average: 0.75, 0.59, 0.35
Threads: 11 total, 1 running, 10 sleeping, 0 stopped, 0 zombie
%Cpu(s): 3.5 us, 0.6 sy, 0.0 ni, 95.9 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem: 2046460 total, 1924856 used, 121604 free, 14396 buffers
KiB Swap: 1048572 total, 0 used, 1048572 free. 1192532 cached Mem

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
10 root 20 0 2557160 289824 15872 R 79.3 14.2 0:41.49 java
11 root 20 0 2557160 289824 15872 S 13.2 14.2 0:06.78 java

二、转换线程 ID 为 16 进制

1
2
3
printf "%x\n" <tid>
// printf "%x\n" 10
// a

三、利用 JDK 提供的工具 jstack 打印导出线程信息

阅读全文 »

什么是Spring Boot Admin?

Spring Boot Admin是一个用于管理和监控Spring Boot应用程序的Web应用程序。应用程序通过我们的Spring Boot Admin Client(通过HTTP)注册,或者使用Spring Cloud(例如Eureka, Consul)进行注册。

入门

设置Admin Server服务

  • 添加Spring Boot Admin Server starter依赖:
阅读全文 »

使用场景

在实际工作中,重处理是一个非常常见的场景,比如:发送消息失败,调用远程服务失败,争抢锁失败,等等,这些错误可能是因为网络波动造成的,等待过后重处理就能成功.通常来说,会用try/catch,while循环之类的语法来进行重处理,但是这样的做法缺乏统一性,并且不是很方便,要多写很多代码.然而spring-retry却可以通过注解,在不入侵原有业务逻辑代码的方式下,优雅的实现重处理功能.

Maven Dependencies

1
2
3
4
5
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
<version>1.2.5.RELEASE</version>
</dependency>

如何启用

阅读全文 »