Redis数据结构-链表
链表被广泛用于实现Redis的各种功能,比如列表键、发布与订阅、慢查询、监视器等。
定义12345678typedef struct listNode { // 前置节点 struct listNode *prev; // 后置节点 struct listNode *next; // 节点的值 void *value;} listNode;
多个这样的 listNode 节点形成一个双向链表,并且在Redis中使用了 list 结构来管理这个双向两边,使得操作更加方便
1234567891011121314typedef struct list { // 表头节点 listNode *head; // 表尾节点 listNode *tail; // 节点值复制函数 void *(*dup)(void *ptr); // 节点值释放函数 void (*free)(void *ptr); // 节点值对比函数 int (*match)(void *ptr, voi ...
Reids数据结构-SDS
定义简单动态字符串(SDS)
12345678struct sdshdr { // buf 中已占用空间的长度 int len; // buf 中剩余可用空间的长度 int free; // 数据空间 char buf[];};
用SDS表示 “Redis” 字符串,其中:
free:值为0,表示该SDS没有任何未分配的空间
len:值为5,表示该SDS保存了一个五字节长的字符串
buf:是 char 类型的数组,表示存储的字符串,其中最后一个子节保存了空字符 \0
SDS与C字符串获取字符串长度由于C字符串并不记录自己的长度信息,所以为了获取一个C字符串的长度,程序必须遍历这个字符串,直到遇到空字符 \0 为止,这个操作的时间复杂度为 O(n)
与C字符串不同,SDS在新增或者更新的时候就会改变 len 的值来记录当前字符串的长度,获取字符串长度直接读取 len 即可,因此复杂度为 O(1),保证了 STRLEN 的性能
杜绝缓冲区溢出在函数库<string.h> 中的 strcat 函数可以将字符串 sr ...
双亲委派
双亲委派当某个类加载器要加载某个类时,它会先将加载任务委托给父类加载器,一直递归到顶层,如果父加载器没有加载这个类,自己才会尝试加载这个类。
类加载器的类别BootstrapClassLoader(启动类加载器)该加载器由C++编写,负责加载rt.jar、resources.jar 等核心库,可以通过Launcher.getBootstrapClassPath().getURLs() 来获取 BootstrapClassLoader 的加载路径。在Java中无法直接获取该加载器的引用和信息
ExtClassLoader(标准扩展类加载器)ExtClassLoader 主要负责加载系统变量java.ext.dirs 中的类,如果不指定,则默认为加载路径为 %JAVA_HOME%/jre/lib/ext。该加载器实现路径位于 sun.misc.Launcher$ExtClassLoader。父加载器是BootstrapClassLoader(由C++实现)
AppClassLoader(系统类加载器)负责加载classpath下的类,父加载器是ExtClassLoader,实现路径位于su ...
AMQP
AMQP是什么 Advanced Message Queuing Protocol(高级消息队列协议), 一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。 最典型的实现是以Erlang开发的RabbitMQ
AMQP 模型
Exchange(交换机):接收发布者发送的消息,并且根据对应交换机的路由规则,将消息路由到队列中
Queue(队列):存储消息,并将消息发送给订阅该队列的消费者
Binding:定义Exchange和Queue的关系,提供交换机到队列的路由关系
交换机 Exchange 交换机,生产者将消息发送到交换机,交换机根据路由规则将消息路由一个或多个队列中。而路由规则受 Exchange 的类型和绑定(binding) 关系的影响。AMQP 0-9-1 broker 提供了如下 四个 exchange 类型:
类型
功能
Direct Exchange
直连交换机,任何绑定在交换器上的队列,只要它的路由键和发布消息时的一致,它就能收到消息。
Fanout Exchange
所有发往fanou ...
启动springboot-jar的流程
SpringBoot 程序是如何通过java -jar 启动的
SpringBoot打包方式主要有 jar 和 war 两种,以下仅针对 jar 进行分析
MANIFEST.MF当我们将程序打成 Jar,我们总会发现在 META-INF 文件夹中有一个 MANIFEST.MF 文件,该文件包含了该 Jar 包的主要信息。如果算可执行的 Jar 包,该文件中还会包含一个 Main-Class 属性,表明方法入口。以下是一个 SpringBoot 程序的 MANIFEST.MF 内容
123456789101112Manifest-Version: 1.0Spring-Boot-Classpath-Index: BOOT-INF/classpath.idxImplementation-Title: demoImplementation-Version: 0.0.1-SNAPSHOTStart-Class: com.yxd.es.DemoApplicationSpring-Boot-Classes: BOOT-INF/classes/Spring-Boot-Li ...
实现SpringBoot自动装配
SpringBootApplicationSpringBoot的启动类上面,都有一个@SpringBootApplication 注解,该注解主要由以下注解组成:
EnableAutoConfiguration
ComponentScan
SpringBootConfiguration
其中@EnableAutoConfiguration是我们实现自动装配的重要注解,其中最主要的构成是:@Import(AutoConfigurationImportSelector.class),导入了一个AutoConfigurationImportSelector类
该类的selectImports()最终会调用SpringFactoriesLoader的loadSpringFactories方法,而该方法会从META-INF/spring.factories获取配置,从而实现自动装配
ImportSelector作用是收集需要导入的配置类, 可以通过指定的选择条件来决定哪些类被注册到Spring中
实现自定义的ImportSelector类
123456public class FormatS ...
Mybatis数据源切换
记录一下自己通过 AbstractRoutingDataSource 和 Mybatis 插件实现读写分离的代码(参考了网上的一些思路)
一、AbstractRoutingDataSourceSpring 中提供了 AbstractRoutingDataSource 类,可以根据用户自定义的规则选择当前的数据源,这样我们可以在执行 SQL 前来决定使用哪个数据源,实现动态路由。因此以下代码实际上都是围绕 AbstractRoutingDataSource 来实现的
# 1.1 DynamicRoutingDataSource.java1234567public class DynamicRoutingDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DynamicDataSourceContextHolder.get(); }}
我们通过实现AbstractRoutingD ...
Mybatis-插件
介绍Mybatis 通过提供插件机制,可让用户根据自己的需求对 Mybatis 的功能实现增强。我们常用的如 PageHelper、Mybatis-plus 等都用到了Mybatis 的插件机制
拦截对象众所周知,Mybatis 中有以下四种可供拦截的核心对象
Executor: 执行器的拦截,用于执行增删改查操作
ParameterHandler:SQL参数处理器
ResultSetHandler:SQL执行的返回结果集处理器
StatementHandler:数据库的处理对象,用于执行SQL语句
通过拦截这四个对象,我们便可在 Mybatis 执行的过程中 “插一脚”
自定义插件自定义一个简单的输出查询语句SQL的插件
1234567891011121314151617181920212223242526272829303132@Intercepts({ @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, ...
fail-fast与fail-safe
fail-fast(快速失败)与 fail-safe(安全失败)
fail-fast在用迭代器遍历一个集合对象时,如果遍历过程中对集合对象的内容进行了修改(增加、删除、修改),则会抛出Concurrent Modification Exception。
java.util 中的非线程安全集合的迭代机制都是基于 fail-fast,这里以 ArrayList 为例
原理在对 ArrayList 的结构进行修改的时候,会修改 modCount 属性,该属性可以理解为 ArrayList 当前结构的版本号
在迭代器创建的时候,会记录 modCount 的值。在迭代的过程中,会判断 modCount 是否被修改,如果 modCount 与原先不一致,则抛出 ConcurrentModificationException 异常
12345678910111213141516private class Itr implements Iterator<E> { int expectedModCount = modCount; Itr() { ...
ThreadLocal源码分析
源码分析ThreadLocalMap学习ThreadLocal之前有必要先学习一下它的内部类ThreadLocalMap
1. 数据结构1234567891011121314151617/** * The initial capacity -- MUST be a power of tw */private static final int INITIAL_CAPACITY = 16;/** * The table, resized as necessary. * table.length MUST always be a power of two. */private Entry[] table;/** * The number of entries in the table. */private int size = 0;/** * The next size value at which to resize. */private int threshold; // Default to 0
与HashMap不同的是,TheadLocalMap 没有负载因子这个变量,但实际上负载 ...