6. 发布与订阅
Redis 提供了基于“发布/订阅”模式的消息机制,发送者(publish)发布消息,订阅者(subscribe)接收消息,两者之间不需要进行直接通信,他们之间通过频道进行消息传递。发布者向指定的频道(channel)发布消息,订阅了该频道的订阅者都可以接收到该消息。
Redis 中相关的命令如下:
PSUBSCRIBE pattern [pattern …]:订阅一个或多个符合给定模式的频道。
PUBSUB subcommand [argument [argument …]]:查看订阅与发布系统状态。
PUBLISH channel message :将信息发送到指定的频道。
PUNSUBSCRIBE [pattern [pattern …]]:退订所有给定模式的频道。
SUBSCRIBE channel [channel …]:订阅给定的一个或多个频道的信息。
UNSUBSCRIBE [channel [channel …]]:退订给定的频道。
7. HandlerMapping 组件(一)之 AbstractHandlerMapping
类图HandlerMapping 的子类比较多,整体类图如下:
绿框 AbstractHandlerMapping 抽象类,实现了【获得请求对应的处理器和拦截器们】的骨架逻辑,而暴露 #getHandlerInternal(HttpServletRequest request) 抽象方法,交由子类实现。这就是我们常说的“模板方法模式” 。
AbstractHandlerMapping 的子类,分成两派,分别是:
红框 AbstractUrlHandlerMapping 系,基于 URL 进行匹配。实际我们开发时,这种方式已经基本不用了,被 @RequestMapping 等注解的方式所取代。不过,Spring MVC 内置的一些路径匹配,还是使用这种方式。
黄框 AbstractHandlerMethodMapping 系,基于 Method 进行匹配。@RequestMapping 等注解的方式
白框 MatchableHandlerMapping 接口,定义判断请求和指定 pattern 路径是否匹配的接口方法。
AbstractHandlerMappi ...
7. 内存回收(新生代、老生代)
年轻代GC过程当需要在堆中创建一个新的对象,而年轻代内存不足时触发一次GC,在年轻代触发的GC称为普通GC,Minor GC。注意到年轻代中的对象都是存活时间较短的对象,所以适合使用复制算法。这里肯定不会使用两倍的内存来实现复制算法了,牛人们是这样解决的,把年轻代内存组成是80%的Eden、10%的From Space和10%的To Space,然后在这些内存区域直接进行复制。
刚开始创建的对象是在Eden中,此时Eden中有对象,而两个survivor区没有对象,都是空闲区间。第一次Minor GC后,存活的对象被放到其中一个survivor,Eden中的内存空间直接被回收。在下一次GC到来时,Eden和一个survivor中又创建满了对象,这个时候GC清除的就是Eden和这个放满对象的survivor组成的大区域(占90%),Minor GC使用复制算法把活的对象复制到另一个空闲的survivor区间,然后直接回收之前90%的内存。周而复始。始终会有一个10%空闲的survivor区间,作为下一次Minor GC存放对象的准备空间。
要完成上面的算法,每次Minor GC过程 ...
7. JVM调优
代大小的调优在不采用G1的情况下,通常minor GC会快于Full GC,在代调优的参数上,最关键的是:-Xms -Xmx -Xmn -XX:SurvivorRadio -XX:MaxTenuringThreshold
Xms和Xmx设定为相同的值
避免运行时要不断的扩展JVM的内存空间,这个值决定了JVM heap所能使用的最大空间
Xmn决定了新生代(New Generation)大小
新生代中Eden、S0、S1三个区域的比例,通过-XX:SurvivorRadio控制
XX:MaxTenuringThreshold控制对象经历多少次Minor GC后才转入旧生代,通常又被称为:新生代存活周期
此参数只在串行GC有效,其他GC方式由Sun JDK自��决定
避免新生代设置过小-新生代过小:
minor GC次数更加频繁
minor对象直接进入旧生代,会触发full GC
调整的原则:
不调大JVM Heap的情况下,尽可能放大新生代的空间,尽量让对象在新生代minor GC阶段被回收,但新生代空间也不可过大
能够调大JVM Heap的情况下 ...
7. ⼆级缓存
二级缓存构建在一级缓存之上,在收到查询请求时,MyBatis首先会查询二级缓存。若二级缓存未命中,再去查询一级缓存。
二级缓存和具体的命名空间绑定
一级缓存和SqlSession绑定
在按照 MyBatis 规范使用SqlSession的情况下,一级缓存不存在并发问题(因为采用了LOCK)。二级缓存则不然,二级缓存可在多个命名空间共享。这种情况下,会存在并发问题,因此需要针对性的去处理。
除了并发问题,二级缓存还存在事务问题
二级缓存的逻辑12345678910111213141516171819202122232425262728293031323334353637// -☆- CachingExecutorpublic <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException { BoundSql boundSql = m ...
7. 处理查询结果
MyBatis 可以将查询结果,即结果集 ResultSet 自动映射成实体类对象。这样使用者就无需再手动操作结果集,并将数据填充到实体类对象中。这可大大降低开发的工作量,提高工作效率。
结果集的处理工作由结果集处理器ResultSetHandler执行。ResultSetHandler是一个接口,它只有一个实现类 DefaultResultSetHandler。结果集的处理入口方法是handleResultSets,下面来看一下该方法的实现。
handleResultSets1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950public List<Object> handleResultSets(Statement stmt) throws SQLException { final List<Object> multipleResults = new ArrayList<Object>(); ...
7. 解析 SQL 语句节点
分析映射文件中剩余的几个节点,分别是select、insert、update以及delete等等。这几个节点中存储的是相同的内容,都是 SQL 语句,所以这几个节点的解析过程也是相同的
代码分析
12345678910111213141516171819202122232425private void buildStatementFromContext(List<XNode> list) { if (configuration.getDatabaseId() != null) { // 调用重载方法构建 Statement buildStatementFromContext(list, configuration.getDatabaseId()); } // 调用重载方法构建 Statement,requiredDatabaseId 参数为空 buildStatementFromContext(list, null);}private void buildStatementFro ...
7. 解析environments节点
事务管理器和数据源是配置在节点中的。它们的配置大致如下
实例1234567891011<environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value=&q ...
7. 确保 Web 安全的 HTTPS
HTTP 的缺点
通信使用明文(不加密),内容可能会被窃听
不验证通信方的身份,因此有可能遭遇伪装
无法证明报文的完整性,所以有可能已遭篡改
除此之外,HTTP 本身还有很多缺点。而且,还有像某些特定的 Web 服务器和特定的 Web 浏览器在实际应用中存在的不足
通信使用明文可能会被窃听由于 HTTP 本身不具备加密的功能,所以也无法做到对通信整体(使用HTTP协议通信的请求和响应的内容)进行加密。即,HTTP报文使用明文(指未经过加密的报文)方式��送
TCP/IP 是可能被窃听的网络按 TCP/IP 协议族的工作机制,通信内容在所有的通信线路上都有可能遭到窥视。
即使已经过加密处理的通信,也会被窥视到通信内容,这点和未加密的通信是相同的。只是说如果通信经过加密,就有可能让人无法破解报文信息的含义,但加密处理后的报文信息本身还是会被看到的
窃听相同段上的通信并非难事。只需要收集在互联网上流动的数据包(帧)就行了。对于收集来的数据包的解析工作
加密处理防止被窃听在目前大家正在研究的如何防止窃听保护信息的几种对策中,最为普及的就是加密技术。加密的对象可 ...
7. 排查Redis中的慢查询
慢查询的作用:通过慢查询分析,找到有问题的命令进行优化。
Redis 执行命令分为四个步骤:发送命令、命令排队、执行命令、返回结果。需要注意的是,慢查询只统计步骤 3 的时间,所以没有慢查询并不代表客户端没有超时问题。
Redis 慢查询有两个参数需要配置:
slowlog-log-slower-than:设置慢查询预设的超时阈值,单位是微秒
slowlog-max-len:表示慢查询日志存储的条数
slowlog-log-slower-than表示的是慢查询预设的超时阈值。它所阐述的意思是如果某条命令(如 key *) 执行”很慢“,执行时间超过了设置的阈值,那么这条命令将会被记录到慢查询日志中。
若设置 slowlog-log-slower-than = 0,则会记录所有命令
若设置 slowlog-log-slower-than < 0,则不会记录任何命令
slowlog-max-lenRedis 会记录慢查询日志,但是会存储在哪里呢?实际上 Redis 会使用一个列表来存储慢查询日志,slowlog-max-len 就是该列表的最大长度。一个命令 ...