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并不是一个单独的协议,而是对 ...
前言之前给小伙伴们科普ClickHouse集群的时候,我曾经提到ClickHouse集群几乎是去中心化的(decentralized),亦即集群中各个CK实例是对等的,没有主从之分。集群上的复制表、分布式表机制只是靠外部ZooKeeper做分布式协调工作。想了想,又补了一句:
“其实单纯靠P2P互相通信就能维护完整的集群状态,实现集群自治,比如Redis Cluster。”
当然限于时间没有展开说。这个周末休息够了,难得有空,来随便讲两句吧。
在官方Redis Cluster出现之前,要实现集群化Redis都是依靠Sharding+Proxy技术,如Twemproxy和Codis(笔者之前也写过Codis集群的事儿)。而官方Redis Cluster走了去中心化的路,其通信基础就是Gossip协议,同时该协议还能保证一致性和可用性。本文先来介绍一下它。
Gossip协议简介
最近几个月一直在看《Friends》下饭。认为自己从不gossip的Rachel一语道破了gossip的本质。
现实生活中的流言八卦传播的机制就是“I hear something and I pass th ...
关于redis的集群,官网介绍比较全面了。https://redis.io/topics/cluster-spec
设计目标:
High performance and linear scalability up to 1000 nodes. There are no proxies, asynchronous replication is used, and no merge operations are performed on values.
高达1000个节点的线性可扩展性。没有代理,使用异步复制,并且在进行赋值时没有合并操作
Acceptable degree of write safety: the system tries (in a best-effort way) to retain all the writes originating from clients connected with the majority of the master nodes. Usually there are small windows where acknowledge ...
(0) ChannelPipeline的实例
ChannelPipeline的使用实例
12345678910111213141516171819202122private void connect(String host,int port){ EventLoopGroup group = new NioEventLoopGroup(); try { Bootstrap b = new Bootstrap(); b.group(group).channel(NioSocketChannel.class).option(ChannelOption.TCP_NODELAY,true) .handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel socketCha ...