4. 理解 pipeline 管道
Redis 性能瓶颈主要是网络,主要原因就在于 Redis 执行命令的时间通常在微妙级别。正常情况下,我们执行一条 Redis 命令流程要经过如下几个步骤:
客户端发送 Redis 命令,阻塞等待 Redis 应答
Redis 接收到命令,执行命令
应答,客户端收到响应信息
其中 1 、3 称之为一次 RTT(Round Trip Time)。在这种情况下,如果同时执行大量命令,那当前命令需要等待上一条命令应答完成后才会执行,这个过程不仅仅只有多次 RTT,还有频繁的调用系统 IO,发送网络请求,如下图:把大量的时间消耗在来回路上,真正办事的时间就只有一点点,这种做法是非常不明智且低效的,为了解决这种低效的做法,pipeline 出现了,它允许客户端一次性发送多条命令,减少 RTT 和 IO 的调用次数(IO 调用涉及到用户态到内核态之间的切换)。如下图:
实现原理要支持 pipeline,除了需要 Redis 服务端支持,也需要各个客户端的支持,例如 jedis 就对 pipeline 提供了很好的支持。对于服务端来说,所需要的就是能够处理客户端通过一个 TCP 连接发送的多 ...
4. nginx 浏览器缓存配置
浏览器缓存(Browser Caching)是为了加速浏览,浏览器在用户磁盘上对最近请求过的文档进行存储,当访问者再次请求这个页面时,浏览器就可以从本地磁盘显示文档,这样就可以加速页面的阅览。缓存的方式节约了网络的资源,提高了网络的效率。
浏览器缓存可以通过expires指令输出Header头来实现,expires指令的语法如下:
语法:expires [time|epoch|max|off]
默认值:expires off
作用域:http,server,location
用途:
控制HTTP应答中的“Expires”和“Cache-Control”的Header头信息(起到控制页面缓存的作用。可以在time值中使用正数或负数。
“Expires”头标的值将通过:当前系统时间加上您设定的time值来获得。
对常见格式的图片、Flash文件在浏览器本地缓存30天
123location ~.*\.(gif|jpg|jpeg|png|bmp|swf)$ { expires 30d;}
对js、css文件在浏览器本地缓存1小时
123location ~ ...
4. B+树
B+树其实和B树是非常相似的。相同点:
根节点至少一个元素
非根节点元素范围:m/2 <= k <= m-1
不同点:
B+树有两种类型的节点:内部结点(也称索引结点)和叶子结点。内部节点就是非叶子节点,内部节点不存储数据,只存储索引,数据都存储在叶子节点。
内部结点中的key都按照从小到大的顺序排列,对于内部结点中的一个key,左树中的所有key都小于它,右子树中的key都大于等于它。叶子结点中的记录也按照key的大小排列。
每个叶子结点都存有相邻叶子结点的指针,叶子结点本身依关键字的大小自小而大顺序链接
父节点存有右孩子的第一个元素的索引
插入
插入5,10,15,20
插入25,此时元素数量大于4个了,分裂
接着插入26,30,继续分裂
删除对于删除操作是比B树简单一些的,因为叶子节点有指针的存在。
向兄弟节点借元素时,不需要通过父节点了,而是可以直接通过兄弟节点移动即可(前提是兄弟节点的元素大于m/2),然后更新父节点的索引。
如果兄弟节点的元素不大于m/2(兄弟节点也没有多余的元素), ...
5. 组件一览
概述12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970// DispatcherServlet.java/** MultipartResolver used by this servlet. */@Nullableprivate MultipartResolver multipartResolver;/** LocaleResolver used by this servlet. */@Nullableprivate LocaleResolver localeResolver;/** ThemeResolver used by this servlet. */@Nullableprivate ThemeResolver themeResolver;/** List of HandlerMappings used by this servlet. */@Nullablepr ...
5. 内存回收(收集器模式)
收集器JVM通过GC来回收堆和方法区中的内存,GC基本原理:
找到程序中不再被使用的对象
回收这些对象所占用的内存
通常采用收集器方式实现GC,主要的收集器有:
引用计数收集器
跟踪收集器
1. 引用计数收集器采用分散式的管理方式,通过计数器记录对象是否被引用。 当计数器为零时,代表该对象不再被使用
引用计数法描述的算法为:给对象增加一个引用计数器,每当有一个地方引用它时,计数器就+1;当引用失效时,计数器就-1;任何时刻计数器为0的对象就是不能再被使用的,即对象已“死”。
优点
算法实现简单
缺点
不能解决对象之间循环引用的问题。有垃圾对象不能被正确识别,这对垃圾回收来说是很致命的,所以GC并没有使用这种搜索算法
2. 跟踪收集器/根搜索法/可达性分析算法以一些特定的对象作为基础原始对象,或者称作“根”,不断往下搜索,到达某一个对象的路径称为引用链。
如果一个对象和根对象之间有引用链,即根对象到这个对象是可到达的,则这个对象是活着的,不是垃圾,还不能回收。例如,假设有根对象O,O引用了A对象,同时A对象引用了B对象,B对象又引用了 ...
5. 程序执行缓慢原因分析
原因分析
锁竞争激烈
如数据库连接池中连接数为 10 ,有 50 个或更多线程需要进行数据操作。
未充分使用硬件资源
如机器为双核 CPU ,但程序中都是单线程串行的操作
数据量增长
数据量增长通常是造成程序执行慢的典型原因,当数据库中单表的数据从 100 万上涨到 1 亿后,数据库的读写速度将大幅下降
5. CacheKey
在 MyBatis 中,引入缓存的目的是为提高查询效率,降低数据库压力。既然 MyBatis引入了缓存,那么缓存中的key和value的值分别是什么?
可能很容易能回答出value的内容,不就是SQL的查询结果吗。那key是什么呢?是字符串,还是其他什么对象?
如果是字符串的话,那么大家首先能想到的是用SQL语句作为key。但这是不对的,比如:
1SELECT * FROM author where id > ?
id > 1 和 id > 10 查出来的结果可能是不同的,所以我们不能简单的使用SQL语句作为key
运行时参数将会影响查询结果,因此我们的key应该涵盖运行时参数。
除此之外,进行分页查询,查询结果也会不同,因此key也应该涵盖分页参数。
综上,我们不能使用简单的 SQL 语句作为 key。应该考虑使用一种复合对象,能涵盖可影响查询结果的因子。在 MyBatis 中,这种复合对象就是 CacheKey。
123456789101112131415161718192021public class CacheKey implements Clone ...
5. 设置运⾏时参数到 SQL 中
JDBC 提供了三种 Statement 接口,分别是 Statement 、 PreparedStatement 和CallableStatement。他们的关系如下:
Statement 接口提供了执行 SQL,获取执行结果等基本功能。
PreparedStatement 在此基础上,对IN类型的参数提供了支持。使得我们可以使用运行时参数替换 SQL 中的问号?占位符,而不用手动拼接 SQL。
CallableStatement 则是在PreparedStatement基础上,对OUT类型的参数提供了支持,该种类型的参数用于保存存储过程输出的结果。
123456789101112// -☆- SimpleExecutorprivate Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException { Statement stmt; // 获取数据库连接 Connection connection = getConnecti ...
5. 解析resultMap节点
resultMap 是 MyBatis 框架中常用的特性,主要用于映射结果。
resutMap元素是 MyBatis 中最重要最强大的元素。它可以让你从 90% 的 JDBC ResutSets数据提取代码中解放出来,并在一些情形下允许你做一些JDBC不支持的事情。实际上,在对复杂语句进行联合映射的时候,它很可能可以代替数千行的同等功能的代码。ResutMap的设计思想是,简单的语句不需要明确的结果映射,而复杂一点的语句只需要描述它们的关系就行了。
通过 resultMap 和自动映射,可以让 MyBatis 帮助我们完成ResultSet → Object 的映射,这将会大大提高了开发效率。
解析过程
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475// -☆- XMLMapperBuilderprivate void resultMapElem ...
5. 解析typeAliases节点
在 MyBatis 中,我们可以为自己写的一些类定义一个别名。这样在使用的时候,只需要输入别名即可,无需再把全限定的类名写出来。在 MyBatis 中,我们有两种方式进行别名配置。• 第一种是仅配置包名,让 MyBatis 去扫描包中的类型,并根据类型得到相应的别名。这种方式可配合 Alias 注解使用,即通过注解为某个类配置别名,而不是让 MyBatis 按照默认规则生成别名。• 第二种方式是通过手动的方式,明确为某个类型配置别名。第一种配置方式
1234<typeAliases> <package name="xyz.coolblog.chapter2.model1"/> <package name="xyz.coolblog.chapter2.model2"/></typeAliases>
第二种配置方式
1234<typeAliases> <typeAlias alias="article" type="xyz.coolblog. ...