1、背景 在当前微服务体系架构中,有很多服务例如,在 特征组装 与 排序等场景都需要有大量的数据支撑,快速读取这些数据对提升整个服务于的性能起着至关重要的作用。
缓存在各大系统中应用非常广泛。尤其是业务程序所依赖的数据可能在各种类型的数据库上(mysql、hive 等),那么如果想要获取到这些数据需要通过网络来访问。再加上往往数据量又很庞大,网络传输的耗时,自然会增加系统的相应时间。为了降低相应时间,业务程序可以将从数据库中读取到的部分数据,缓存在本地服务器可以很方便快速的直接使用。
缓存框架OHC基于Java语言实现,并以类库的形式供其他Java程序调用,是一种以单机模式运行的堆外缓存。
2、OHC 简介 缓存的分类与实现机制多种多样,包括单机缓存与分布式缓存等等。具体到JVM应用,又可以分为堆内缓存和堆外缓存。
OHC 全称为 off-heap-cache,即堆外缓存,是一款基于Java 的 key-value 堆外缓存框架。
OHC是2015年针对 Apache Cassandra 开发的缓存框架,后来从 Cassandra 项目中独立出来,成为单独的类库,其 ...
netty
未读12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849public class RecyclerTest { static class WrapRecycler{ private boolean tmp ; private final static Recycler<WrapRecycler> RECYCLER = new Recycler<WrapRecycler>() { @Override protected WrapRecycler newObject(Handle<WrapRecycler> handle) { return new WrapRecycler(handle); } }; Recycler. ...
redis
未读启动节点通过命令配置集群(a. 加入节点 b. 分派slot c. 添加slave)接受命令处理
根据key,转发到不同的节点
特殊的标记{…},可以分派key到相同的节点,{} 不能在key的结尾。如果有{…} ,hash算法则使用{与}中间的字符串来计算,所以一定要在{}中间有字符,不然所有的key将会分配到一个节点。
命令中有多个key,如果这些key不在相同的slot(即使在相同的节点也不行),则返回错误(getNodeByQuery)
根据key获取节点(getNodeByQuery)
12345678910111. 根据key 计算 slot 值(keyHashSlot)2. 如果 slot ,没有对应的 node,则返回错误 CLUSTER_REDIR_DOWN_UNBOUND,对应返回消息:-CLUSTERDOWN3. 如果多个key,对应不同的slot,则返回错误 CLUSTER_REDIR_CROSS_SLOT,对应的返回消息:-CROSSSLOT。exec 命令命令中的多条子命令包含的所有 key 也需要是在同一个slot中。4. 如果命令中没有key,则返 ...
redis
未读
redis cluster 是 redis 提供的分布式数据库方案,通过在多个 redis 节点之间分片(sharding)来进行数据共享。并能在部分节点故障的情况下继续运行。
redis 集群的基本存储单位是槽(slot),一个集群有2^14=16384个槽。每一个槽的key存放在集群中的唯一一个master节点中,每一个槽还有0~N个slave节点。
集群简介
redis集群每个节点都和其他节点保持连接,需要两个端口。其中一个数据端口(例如7000用来为客户端提供服务以及同其他服务端交换数据。另外一个总线端口(数据端口号+10000,其中偏移量10000是固定的)用来在节点之间传送控制信息。要让redis集群系统正常运行,需要:
每个节点的数据端口对 Client 以及其他集群节点可见
每个节点的总线端口对其他节点可见
redis cluster 数据分片(sharding)
redis 集群有16384个哈希槽(hash slot),其中散列算法是简单的取 key 的 CRC16 模 16384
集群中的每一个节点负责哈希槽的一个子集
slot 可以 ...
redis
未读Redis作为内存数据库,拥有非常高的性能,单个实例的QPS能够达到10W左右。但我们在使用Redis时,经常时不时会出现访问延迟很大的情况,如果你不知道Redis的内部实现原理,在排查问题时就会一头雾水。
很多时候,Redis出现访问延迟变大,都与我们的使用不当或运维不合理导致的。
这篇文章我们就来分析一下Redis在使用过程中,经常会遇到的延迟问题以及如何定位和分析。
使用复杂度高的命令如果在使用Redis时,发现访问延迟突然增大,如何进行排查?
首先,第一步,建议你去查看一下Redis的慢日志。Redis提供了慢日志命令的统计功能,我们通过以下设置,就可以查看有哪些命令在执行时延迟比较大。
首先设置Redis的慢日志阈值,只有超过阈值的命令才会被记录,这里的单位是微妙,例如设置慢日志的阈值为5毫秒,同时设置只保留最近1000条慢日志记录:
1234# 命令执行超过5毫秒记录慢日志CONFIG SET slowlog-log-slower-than 5000# 只保留最近1000条慢日志CONFIG SET slowlog-max-len 1000
设置完成之后,所有执行的命令如 ...
SocketChannel 读取ByteBuf 的过程: 我们首先看NioEventLoop 的processSelectedKey 方法:
1234567891011121314151617181920212223242526272829303132private void processSelectedKey(SelectionKey k, AbstractNioChannel ch) { //获取到channel 中的unsafe final AbstractNioChannel.NioUnsafe unsafe = ch.unsafe(); //如果这个key 不是合法的, 说明这个channel 可能有问题 if (!k.isValid()) { //代码省略 } try { //如果是合法的, 拿到key 的io 事件 int readyOps = k.readyOps(); //链接事件 if ((readyOps & SelectionKey.OP_CONNECT) != 0) ...
堆外缓存写在开头
上文介绍了多级缓存的背景以及多级缓存带来的一些新的问题,本文将重点介绍本地缓存。
通过本文您可以了解到:
本地缓存的一些开源解决方案
堆外缓存的一种实现OHC
使用堆外缓存需要注意的问题:序列化、内存管理、容量评估等
开源实现本地缓存的开源实现也有不少,对于堆内缓存的开源方案则更多,比如Guava或者Ehcache,这个选择相对比较容易。这里我们重点关注的是堆外缓存的开源实现。了解到的主要有:
Ehcache 3.0:3.0基于其商业公司一个非开源的堆外组件的实现
Chronical Map:LGPL V3的license, 高级特性非开源
OHC:来源于Cassandra 3.0, Apache v2
Ignite: 一个规模宏大的内存计算框架,堆外缓存只是它的冰山一角的一角,Apache项目
选型主要考虑成熟度、License、功能、性能、代码质量等等,这里不做详细的方案比较。如果需要进行定制化,一个满足需求的简单且能够驾驭的框架可能是更好的选择。
本文后续的内容以OHC作为基础进行介绍。
堆外缓存关注点序列化从上一节我们大概可以了解到,存放一 ...
堆外内存JVM启动时分配的内存,称为堆内存,与之相对的,在代码中还可以使用堆外内存,比如Netty,广泛使用了堆外内存,但是这部分的内存并不归JVM管理,GC算法并不会对它们进行回收,所以在使用堆外内存时,要格外小心,防止内存一直得不到释放,造成线上故障。
堆外内存的申请和释放JDK的ByteBuffer类提供了一个接口allocateDirect(int capacity)进行堆外内存的申请,底层通过unsafe.allocateMemory(size)实现,接下去看看在JVM层面是如何实现的。
可以发现,最底层是通过malloc方法申请的,但是这块内存需要进行手动释放,JVM并不会进行回收,幸好Unsafe提供了另一个接口freeMemory可以对申请的堆外内存进行释放。
堆外内存的回收机制如果每次申请堆外内存,都需要在代码中显示的释放,对于Java这门语言的设计来说,显然不够合理,既然JVM不会管理这些堆外内存,它们是如何回收的呢?
DirectByteBufferJDK中使用DirectByteBuffer对象来表示堆外内存,每个DirectByteBuffer对象在初始化 ...
一、背景offheap作为摆脱gc的本地缓存来使用,对于缓存大量数据和提升应用的性能大有裨益。
EHCache的offheap层直接使用了Terracotta-OSS开源的offheap-store作为底层实现。
但是offheap-store包含了一系列的算法和数据结构的设计和使用,很多地方借鉴了操作系统的知识,比如内存分页设计,时钟置换算法,内存分配等等,由此可见涉及到内存管理的都是比较复杂的领域,这里仅仅是简单介绍,为后续深入使用铺垫基础。
想了解offheap-store的原因来自于以下几个问题:
由于堆外内存不能存储对象,只能存储序列化后的二进制数据,那么本质就转换为了数据对于内存的需求:
堆外内存如何分配和管理?数据移除后内存如何释放?过期和剔除机制是怎样的?下面针对上面的问题进行一一说明。
二、ehcache offheap putput时序图,由于调用链太长,故分成两部分,第一部分到OffHeapHashMap截止,如下:
此部分调用都是顺序的,调用过程比较简单,这里只介绍一下EhcacheConcurrentOffHeapClockCache类:
EhcacheC ...
Contents
Caused by: java.io.EOFException: SSL peer shut down incorrectly
HTTPS 的 protocols
TLS 与 SSL
发展历史
SSL
TLS
JDK中对 HTTPS 版本的支持情况
JDK 6
JDK 7
JDK 8
JSSE
JSSE 参数调节
查看服务器支持的 HTTPS 协议版本
解决办法
参考资料
Caused by: java.io.EOFException: SSL peer shut down incorrectly在服务器上,发现一个微博爬虫系统偶尔会报这种异常。Google 了下,在 Stackoverflow 上看到相关的回答。所以决定详细了解下这原理。
上面说,明确指定HTTPS的协议版本即可。即:System.setProperty("https.protocols", "TLSv1.1")
HTTPS 的 protocols查看维基百科,关于 HTTPS 的介绍可知:
严格地讲,HTTPS并不是一个单独的协议,而是对 ...
