- 博客(194)
- 问答 (1)
- 收藏
- 关注
原创 《编程高手务实手册-开篇》
《编程高手务实手册》是我这么多年学习工作的抽象和总结出来的方法论以及具体执行指南,有的内容是我实践思考得出,有的内容是大量广泛阅读获取。其实一开始想的名字叫《架构师务实手册》,因为手册里有一个大的部分是专门讲架构师相关的内容的。但是后来想想还是算了,还是“务实”一点吧。
2024-12-09 16:04:41
202
原创 如何讲明白技术
技术是为了解决问题而生的。本质上,技术就是解决问题的方法。问题规模越大,难度越复杂,就要引入多种技术。这些技术组合搭配起来,构成该解决方案的一棵“技术树”。其实,每一个分支和叶子都有多种可选的技术,随着更多的创新出现,这些分支和叶子也在演变,使得整体方案在空间和时间上,能更高效更节省地解决问题。我们对这些分支和叶子技术点的了解和运用,甚至对它们演变的推动,都体现了我们的经验和技能。
2022-09-05 21:47:47
1160
原创 UTF-8 吧啦吧啦
Unicode编码的诞生,是为了解决之前各国的计算机文字编码自成一体的问题。不同国家采用不同的编码,自己用还算正常,但是跨文化交流必然会出问题,更无法解决“在同一篇文档里又要显示中文又要显示韩文还要显示日文”之类的问题。但是Unicode(有个相关的名字是UCS,Universal Coded Character Set,二者基本等价)只确定了码值,或者说,只分配了逻辑代号。至于这些逻辑代号在实际使用中如何存储,如何传输,那是另一个问题。而UTF-8,就是解决存储和传输等问题的“实际方案”。UTF的全名是
2021-12-13 16:04:25
632
原创 Redis 哨兵模式和集群模式中的选主流程
文章目录一、Paxos 算法二、Raft 算法三、哨兵模式的选主流程四、集群模式的选主流程一、Paxos 算法Paxos 算法是一种分布式一致性算法,所谓的分布式一致性算法就是在分布式系统中,可以保证多个节点中数据的值是一致的的算法。为什么需要一致性数据不能存在单个节点(主机)上,否则可能出现单点故障。多个节点(主机)需要保证具有相同的数据。一致性算法就是为了解决上面两个问题。Paxos 是一种强一致性算法,又可以分为:Basic PaxosMulti Paxos二、Raft 算
2021-10-03 10:38:18
1741
1
原创 Drone配合Gogs实现持续集成
Gogs 是一个轻量级Git仓库。Drone是一款基于容器技术的持续集成工具,使用简单的YAML配置文件即可完成复杂的自动化构建、测试、部署任务。1. 可以直接使用docker-compose安装启动新建文件docker-compose.yml :version: "3.8"services: gogs: image: gogs/gogs container_name: my-gogs restart: always networks: dronen
2021-04-27 19:28:00
1133
原创 Redis 中的底层数据结构:SkipList
SkipList 是zset的底层实现之一,它的数据结构定义如下:typedef struct zskiplistNode { //层 struct zskiplistLevel { //前进指针 struct zskiplistNode *forward; //跨度 unsigned int span; } level[]; //后退指针 struct zskiplistNode *backward; //分值 double score; //成员对象 robj *
2021-04-21 12:39:09
513
原创 面试题:如何计算InnoDB中B+树索引的层高
假设有一张user表中有200万条数据,表结构如下:create table user( `id` bigint(64) NOT NULL COMMENT 'id主键', `user_name` varchar(64) DEFAULT NULL COMMENT '用户名' PRIMARY KEY (`id`) USING BTREE) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;bigint 长度为 8 字节,指针大小在 I
2021-04-19 21:13:34
1195
原创 RPC原理以及手写实现一个简单的RPC框架
一、RPC原理一次完整的RPC过程(同步调用)如下图所示:(1)服务消费方(client)以本地调用的方式调用服务;(2)client stub 接收到调用后,负责将方法、参数等信息组装成能够进行网络传输的消息体;(3)client stub 将消息发送给服务端;(4)server stub 将收到的消息进行解码;(5)server stub 将解码后的方法、参数等信息传递给本地服务;(6)本地服务调用实际方法返回结果给 server stub;(7)server stub 将返回结果打包
2021-04-15 11:37:50
233
原创 面试题:Java 线程的状态及其转换
Java线程在运⾏的声明周期中可能处于6种不同的状态,在给定的⼀个时刻,线程只能处于其中的⼀个状态:THE END.
2021-04-13 22:13:26
186
原创 面试题:SpringBoot 自动装配原理
1. @SpringBootApplication注解首先,我们都知道SpringBoot程序的入口是通过@SpringBootApplication注解修饰的一个类,例如:@SpringBootApplicationpublic class DemoApplication { public static void main(String[] args) { SpringApplication.run(ConfigApplication.class, args); }
2021-04-13 21:42:35
10868
原创 Redis 主从复制功能和部分重同步的实现
旧版复制功能在处理断线复制情况时,会重复复制之前已经复制过的部分数据,造成效率低下问题。Redis从2.8版本开始,使用PSYNC命令替代了旧版的SYNC命令来执行复制操作。PSYNC命令具有完整重同步(full synchronization)和部分重同步两种模式(partial synchronization):完整重同步:处理初次复制情况,从服务器(Slave)先让主服务器(Master)创建并发送RDB文件,然后再将主服务器的缓冲区里的命令发送给从服务器,以此完成同步;部分重同步:用于处理断
2021-04-13 18:47:00
508
原创 MySQL中JOIN关键字原理
一、JOIN 简介JOIN 用于根据两个或多个表中的列之间的关系,从这些表中查询数据。例如我们可以通过JOIN来从用户表和订单表两个表中获取数据:SELECT Persons.LastName, Persons.FirstName, Orders.OrderNoFROM PersonsINNER JOIN OrdersON Persons.Id_P = Orders.Id_PORDER BY Persons.LastNameJOIN类型分为以下几种:JOIN: 如果表中有至少一个匹配,则
2021-04-13 13:35:53
319
原创 面试题:热Key的发现和解决
其实热key问题说来也很简单,就是瞬间有几十万的请求去访问某一台Redis(或MySQL)服务器上某个固定的key,这样会造成流量过于集中,达到物理网卡上限,从而导致这台服务器宕机。那么这个key的请求,要么直接打到数据库上,要么就是由于MySQL服务器宕机导致请求失效。一、热Key发现发现热Key的方法主要包括如下几个:1. 凭借业务经验,进行预估哪些是热key其实这个方法还是挺有可行性的。比如某商品在做秒杀,那这个商品的key就可以判断出是热key。缺点很明显,并非所有业务都能预估出哪些key是
2021-04-12 21:52:20
682
原创 面试题:Spring的 IOC和DI 的本质理解
反转控制(Inverse of Control, IOC)思想最核心的地方就是:资源不由提供方和使用方管理,而是通过不使用资源的第三方管理。这样的好处是:资源集中管理,实现资源的可配置和易管理。降低了使用资源双方的依赖程度,也就是我们说的耦合度。依赖注入(Dependency Injection)则是使用方开放接口,在它需要的时候,能够将资源传递进来(注入)。反转控制是目的,依赖注入是手段。通常我们在编程的时候是面向接口编程,也就是不需要关注具体的实现类。这个时候只要通过依赖注入,将需要的
2021-04-12 14:00:35
328
原创 面试题:Java程序中 try,catch和finall 的执行顺序以及方法返回值
1. try,catch,finally中都有return值执行下面的程序:import java.util.*;public static class Test1 { public static void main(String []args) { System.out.println("Output : "+test()); } public static String test(){ try{ System.out
2021-04-12 13:25:05
410
原创 Redis 中的文件事件
1. 事件Redis服务器是一个事件驱动程序,服务器需要处理以下两种事件:文件事件(file event):Redis服务器通过套接字与客户端(或其他Redis服务器)连接,而文件事件就是服务器对套接字操作的抽象。服务器与客户端(或其他Redis服务器)的通信会产生相应的文件事件,而服务器则通过监听并处理这些事件来完成一系列网络通信操作。时间时间(time event):Redis服务器中的一些操作需要在给定的时间点执行,而时间事件就是Redis对这类操作的抽象。2. 文件事件处理器Redis
2021-04-12 11:32:35
495
1
原创 Redis的AOF、RDB和复制功能对过期键的处理
一、过期键1. 设置键的生存时间或过期时间通过EXPIRE命令为键设置过期时间,单位是秒:redis> SET key valueOKredis> EXPIRE key 5(integer) 1redis> GET key //5秒内"value"redis> GET key //5秒后(nil)还可以通过PEXPIRE设置过期时间,单位是毫秒。除了这种设置剩余存活时间的方式,还可以通过EXPIREAT或者PEXPIREAT为键设置具体的过期时间。redi
2021-04-11 17:54:51
965
原创 Spring中的事务
一、使用在方法上加上@Transactional注解:控制事务的传播性:@Transactional(propagation=Propagation.REQUIRED)控制事务的隔离级别:@Transactional(isolation = Isolation.READ_UNCOMMITTED)设置只读:@Transactional(readOnly=true)该属性用于设置当前事务是否为只读事务,设置为true表示只读,false则表示可读写,默认值为false。设置事务的超时性:@
2021-04-10 21:54:45
161
原创 面试题:雪花算法(SnowFlake)如何解决时钟回拨问题
1. 雪花算法雪花算法是一种分布式ID生成算法,首先它生产的是一个64bit位的ID,这64bit位中划分成多段:第1个bit位:保留位,无实际作用第2-42的bit位:这41位表示时间戳,精确到毫秒级别第43-52的bit位:这10位表示专门负责生产ID的工作机器的id第53-64的bit位:这12位表示序列号,也就是1毫秒内可以生成2122^{12}212个不同的ID优点:毫秒数在高位,自增序列在低位,整个ID都是趋势递增的。作为DB表的主键,索引效率高。不依赖数据库等第三方系统
2021-04-10 21:33:43
14198
6
原创 InnoDB 中的意向锁
一、意向锁简介InnoDB 存储引擎既支持行级锁(row-level locking),也支持表级锁,但默认情况下是采用行级锁。InnoDB行锁是通过给索引上的索引项加锁来实现的,InnoDB这种行锁实现特点意味着:只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁!行级锁都是基于索引的,如果一条SQL语句用不到索引是不会使用行级锁的,会使用表级锁。行级锁的缺点是:由于针对的是单行记录(实际是对索引项加锁),如果表内的数据量特别大,在一些情况下需要请求大量的锁资源,
2021-04-10 20:28:40
501
原创 面试题:拦截器,过滤器,监听器的区别和触发顺序
监听器(Listener)@WebListenerpublic class RequestListener implements ServletRequestListener { @Override public void requestDestroyed(ServletRequestEvent sre) { // TODO Auto-generated method stub System.out.println("======销毁监听器=======
2021-04-10 16:58:46
1327
原创 面试题:ThreadLocal 的内存泄漏问题
一、ThreadLocal 简介多线程访问同一个共享变量的时候容易出现并发问题,特别是多个线程对一个变量进行写入的时候,为了保证线程安全,一般使用者在访问共享变量的时候需要进行额外的同步措施才能保证线程安全性。ThreadLocal是除了加锁这种同步方式之外的一种保证一种规避多线程访问出现线程不安全的方法,当我们在创建一个变量后,如果每个线程对其进行访问的时候访问的都是线程自己的变量这样就不会存在线程不安全问题。ThreadLocal是JDK包提供的,它提供线程本地变量,如果创建一个ThreadLocal
2021-04-10 15:40:07
284
原创 RocketMQ 架构简介
1. 总体架构RocketMQ通过主从架构和多副本机制来实现高可用和支撑高并发。Broker有Master和Slave两种角色。一个Master可能有多个Slave。同时还有一个NameServer集群来保存Broker的路由信息,每个Broker都会向NameServer注册,然后每隔30秒发送一个心跳包保持和NameServer的通信。不管是生产者还是消费者,如果想要从RocketMQ中获取消息,都要通过NameServer获取路由信息,再去找到对应的Broker获取消息。SlaveBroke
2021-04-09 22:35:53
477
原创 InnoDB中MVCC的实现原理
多版本并发控制机制(Multi-Version Concurrency Control,MVCC)是InnoDB中用来实现不同隔离级别的。一、undo log 多版本链条每一条数据都有三个隐藏字段:DB_ROW_ID、DB_TRX_ID、DB_ROLL_PTR。其中这个DB_TRX_ID就是最近一次更新这条数据的事务id,DB_ROLL_PTR就是指向了更新这条数据的事务所生成的undo log。举个例子,假设现在有一个事务A(id=50),插入了一条数据,那么此时这条数据的DB_TRX_ID字段就是
2021-04-09 20:33:25
392
原创 InnoDB中B+树索引的具体实现
一、数据页的存储结构磁盘数据文件虽然不是一个数据页对应一个文件,但是数据页之间是通过指针联系的,同时数据页内部的行数据也通过指针关联。其实一个数据页在磁盘文件里就是一段有组织的数据。每个数据页都有两个指针,一个指向前一个数据页的物理地址,一个指向后一个数据页的物理地址。数据页内部的每一行数据都会按照主键大小进行排序存储,同时每一行数据都有一个指向下一行数据位置的指针。此外,每个数据页都有一个页目录,里面保存的是每个记录的主键和所在的数据页地址的映射关系。如下图所示:这样我们每次寻找一条数据的时候,
2021-04-09 17:33:51
350
原创 MySQL 在磁盘上如何存储数据的
一、一行记录的格式首先介绍“行格式”这个概念,我们可以通过行格式来指定表的行存储的格式是什么样的。常见的行式有以下4种:(1)REDUNDANT(2)COMPACT(3)DYNAMIC(4)COMPRESSED各种表格式的特点及缺点:以COMPACT为例,在这种格式下,每一行数据在实际存储时,打给的格式类似于下面这样:变长字段的长度列表,null值列表,数据头,column01的值,column02的值,…,column0n的值注意实际存储的时候没有逗号分隔,这里只是为了方便说明。1.
2021-04-09 12:54:36
917
原创 InnoDB 中的内存结构:缓冲池(Buffer Pool)
我们在对数据库进行增删改操作的时候是不可能直接对磁盘文件上的数据进行操作的,因为一个大磁盘文件的随机读写操作可能都要几百毫秒,那么数据库每秒也就只能处理几百个请求了。所以很自然的就要引入缓存的概念,MySQL的InnoDB存储引擎中就是使用Buffer Pool来实现数据的缓存,增删改的时候先将数据加载到Buffer Pool中,然后配合undo log、redo log以及binlog来保证数据的正常更新。那么Buffer Pool中的保存的数据结构到底是什么样的,我们一起来看看。1. 如何配置Bu
2021-04-08 23:08:26
602
原创 MySQL中一条更新语句的执行过程
首先假设有这么一条SQL更新语句:update users set name='xxx' where id = 10这个语句是如何执行的呢?首先就是我们的客户端通过一个数据库连接将语句发送到MySQL上,然后经过SQL接口,解析器,优化器,执行器几个环节,解析SQL语句,生成执行计划,接着由执行器调用InnoDB存储引擎的接口去实际执行,然后返回结果给客户端。1. 查询数据更新语句的第一步就是查询到对应记录。所以首先就是要查询 “id=10” 的记录。InnoDB在查询的时候会先从缓冲池(Buf
2021-04-08 20:18:54
581
原创 面试题:使用单例模式产生的对象经过序列化和反序列化之后还是原来的对象么?
这个问题的意思就是在我们使用单例模式时首先获取一个对象instance,然后经过了序列化保存到磁盘中(或者网络二进制流),再将磁盘上的二进制文件反序列化为Java程序中的一个对象,问这个对象和原来的instance对象是不是同一个对象。我们用代码来复现一下这个问题:package com.example.demo;import java.io.*;public class SingletonSerializable implements Serializable { private stat
2021-04-06 10:30:53
814
原创 Unsafe 使用详解
Unsafe是jdk提供的一个直接访问操作系统资源的工具类(底层c++实现),它可以直接分配内存,内存复制,copy,提供cpu级别的CAS乐观锁等操作。Unsafe位于sun.misc包下,jdk中的并发编程包juc(java.util.concurrent)基本全部靠Unsafe实现,由此可见其重要性。它的目的是为了增强java语言直接操作底层资源的能力,无疑带来很多方便。但是,使用的同时就得额外小心!它的总体作用如下:1. 获取Unsafe对象Unsafe被设计为单例,并且只允许被引导类加载器(
2021-03-26 14:25:03
1889
原创 ForkJoinPool 应用和原理
ForkJoinPool 类是位于 java.util.concurrent 包下的一个类。它可以将一个大的任务拆分成多个子任务进行并行处理,最后将子任务结果合并成最后的计算结果,并进行输出。一、应用1. 累加import java.util.*;import java.util.concurrent.*;public class ForkJoinSum { /** * 这是一个简单的Join/Fork计算过程,将1—1001数字相加 */ pr
2021-03-25 22:30:15
424
原创 【Spring 源码解析】从AbstractAutowireCapableBean的applyBeanPostProcessorsAfterInitialization()方法看AOP原理
文章目录一、AOP中的动态代理Spring 生成代理对象1. 生成代理对象2. 执行代理方法3. 触发AOP的通知(1)拦截器的生成(2)拦截器的执行从【Bean的生命周期】中得知,在实例化Bean完成之后会调用init方法,然后再调用AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization()方法生成一个代理对象,其实不管是我们getBean()获取到的对象还是AOP中真正使用的对象都是这个代理对象wrap
2020-12-12 11:00:42
483
1
原创 【Spring 源码解析】4、从AbstractApplicationContext.refresh()方法看BeanFactory创建过程
文章目录1. prepareRefresh()方法进行准备工作2. obtainFreshBeanFactory()方法获取BeanFactory2.1 实例化一个DefaultListableBeanFactory对象2.2 BeanFactory定制2.3 Bean加载(1)配置文件加载(2) Bean解析注册(2.1). createBeanDefinitionDocumentReader():(2.2). createReaderContext():(2.3). registerBeanDefini
2020-12-10 16:32:39
508
2
原创 【Spring 源码解析】3、ClassPathXmlApplicationContext和AnnotationConfigApplicationContext
文章目录一、ClassPathXmlApplicationContext1.构造器2. 设置配置文件路径2.1`resolvePath()` 方法:2.2 getEnvironment()方法2.3 resolveRequiredPlaceholders()方法3. `Environment接口`4. PropertySource和PropertySources4. Profile二、AnnotationConfigApplicationContext1. 构造函数:2. register()方法3. re
2020-12-10 13:20:12
2697
空空如也
执行 aapt l -v test.apk 之后显示的信息内容是什么意思?
2015-10-28
TA创建的收藏夹 TA关注的收藏夹
TA关注的人