![](https://img-blog.csdnimg.cn/20201014180756927.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
读书笔记
laoxilaoxi_
码农,邮箱laoxilaoxi@foxmail.com
展开
-
《Redis设计与实现》4.独立功能的实现
一、发布与订阅 通过PUBLISH发布、SUBSCRIBE订阅、PSUBSCRIBE模式订阅组成。 1.频道订阅与退订 虚线为新增订阅,如果channel已经存在,则直接添加到对应链表尾端,如果不存在,则现在pubsub_channels中添加新channel,然后添加节点。 与订阅相反,退订时如果去掉该客户端节点后,channel没有其他订阅者,则将该channel从pubsub_channels中删除。 ...原创 2020-05-21 16:42:39 · 245 阅读 · 0 评论 -
《Redis设计与实现》3.多机数据库的实现
一、复制SLAVEOF 旧版本复制功能:sync同步、command propagate命令传播 同步:当客户端像从服务器发送SLAVEOF 从服务器向主服务器发送SYNC命令 主服务器收到SYNC命令,执行BGSAVE,并使用一个缓冲区缓存从现在开始的命令 BGSAVE完成,将文件发送给从服务器 主服务器将缓冲区的命令发送到从服务器执行 命令传播 主服务器将执行的写命令发送原创 2020-05-21 16:40:46 · 172 阅读 · 0 评论 -
《Redis设计与实现》2.单机数据库的实现
一、数据库 redis的key过期时间设置:EXPIRE设置ttl秒,PEXPIRE设置ttl毫秒,EXPIREAT设置过期时间戳秒,PEXPIREAT设置过期时间戳毫秒。 保存过期时间:redis过期时间存放于expires字典中,其中都是转为PEXPIREAT命令存储的。 删除过期时间:PERSIST key 过期键删除策略:redis采用惰性删除+定期删除 定时删除:设置过期时间的同时,创建定时器,定时器在键过期时立即执行删除操作(内存友好,但CPU不友好原创 2020-05-21 16:33:28 · 162 阅读 · 0 评论 -
《Redis设计与实现》1.数据结构域对象
一、SDS:simple dynamic string int len:已使用的buf长度 int free:未使用的长度 char buf[]:存储字符串 二、链表:双向链表,包含head、tail指针,head的prev为null,tail节点的next为null 三、字典:类似于java hashmap,rehash过程是渐进式的,内部维护一个是否正在rehash的标识,维护一个rehash 四、跳跃表: header头结点 tail尾结点原创 2020-05-21 16:27:49 · 175 阅读 · 0 评论 -
《RabbitMQ实战》11.提升性能,保障安全
一、对速度的需求 消息持久化:持久化消息降低投递性能 消息确认:降低性能 路由算法与绑定规则 direct:查询一条 fanout:忽略路由键,查询所有路由关系 topic:占用内存更多,性能低 二、消息投递 ...原创 2020-05-20 09:36:57 · 225 阅读 · 0 评论 -
《RabbitMQ实战》7.warren和Shovel:故障转移和复制
一、warren模式 模式1:每个MQ服务器都是独立的,当主节点故障后,故障转移工具会将其切换到副节点上,可以发布新消息,消费新消息。待故障节点恢复,也允许消费者重新连接到该节点进行消息消费。 模式2:每个节点是相互独立的,但共享存储,当主节点故障后,故障转移工具会将其切换到副节点上,可以继续发布新消息,也可消费新消息,因为存储共享,也可以消费旧消息。 二、远距离通信和复制 生产者发布一个消息到MQ1服务器的交换器,交换器路由到队列1中,然后通过Shovel复制到MQ2服务.原创 2020-05-20 09:34:22 · 305 阅读 · 0 评论 -
《RabbitMQ实战》6.从故障中恢复
一、为RabbitMQ做负载均衡 二、连接丢失和从故障中恢复 消费者感知恢复,代码如下 while(true){ try{ //建立连接 //创建队列、交换器、绑定关系 //监听队列 }catch(Exception e){ //打印错误 } } 生产者感知恢复,代码如下 send(){ //建立连接 //发送消息 } ...原创 2020-05-20 09:31:36 · 179 阅读 · 0 评论 -
《RabbitMQ实战》5.集群并处理失败
一、集群架构 RabbitMQ始终会记录元数据: 队列元数据:队列的名称及属性(持久化、自动删除) 交换器元数据:交换器名称及属性(持久化) 绑定元数据:消息路由绑定表 vhost元数据:vhost的队列、交换器、绑定关系及安全属性。 二、集群 每个节点都会有完整的交换机与队列元数据,但是仅有一个节点有真正的队列及队列内容,发布消息时,其他节点需要将消息传递给拥有改队列的节点;消费消息亦是如此。 三、镜像队列 创...原创 2020-05-20 09:29:39 · 255 阅读 · 0 评论 -
《RabbitMQ实战》4.解决Rabbit相关问题:编码与模式
一、解耦 接收订单与处理订单解耦 很大程度的提高了接单的吞吐量,并且也很容易进行处理能力的扩展。 订单系统与订单处理也不用关心对方使用的啥语言,降低对接成本。 二、发后即忘 1)批处理:异步化批处理任务。 2)告警通知:可以利用direct或者topic方式 3)并发处理:可以使用fanout模式 三、RabbitMQ实现RPC并等待响应 服务端、客户端与RabbitMQ的调用关系,如下图 服务端、客户端流程图如下 ...原创 2020-05-20 09:28:57 · 252 阅读 · 0 评论 -
《RabbitMQ实战》2.理解消息通信
一、队列 1)消费消息 通过AMQP的basic.consume命令订阅。 通过AMQP的basic.get从队列获取单条消息。 队列有多个消费者,则会采取循环(round-robin)的方式发给消费者。 消息必须确认:可以是通过AMQP的basic.ack显式确认或者订阅队列时设置auto_ack为true。 拒绝消息:可以通过AMQP的basic.reject消息或者消费者从RabbitMQ服务器断开连接。reject的话存在两种情况,requeue设..原创 2020-05-20 09:27:48 · 141 阅读 · 0 评论 -
《深入理解JAVA虚拟机》13.线程安全与锁优化
一、线程安全 代码本身封装了所有必要的正确性保证手段,令调用这个无需关心多线程问题,更无需自己采取任何措施来保证多线程的正确调用。 1)线程安全的实现方法 互斥同步:synchronize、ReentrantLock。 非阻塞同步:CAS自旋,其中ABA问题一般不影响正确性。 无同步方案:可重入代码(传入相同的参数,就能返回相同的结果)、线程本地存储(ThreadLocal) 二、锁优化 自适应性自旋、锁消除、锁粗化、轻量级锁、偏向锁等 1)自旋锁与自...原创 2020-05-13 09:15:43 · 130 阅读 · 0 评论 -
《深入理解JAVA虚拟机》12.Java内存模型与线程
一、硬件的效率与一致性 处理器、高速缓存、主内存间的交互关系,如下图 二、Java内存模型 1)主内存与工作内存 主内存:所有的变量都存储在主内存。 工作内存:每个前程都有自己的工作内存,保存了被该线程使用到的变量的主内存副本拷贝。 线程、工作内存、主内存的交互关系,如下图 2)内存间的交互操作(操作:作用域,作用) lock(锁定):主内存,把一个变量标识为一个线程独占状态。 unlock(解锁):主内存,把一...原创 2020-05-13 09:13:22 · 137 阅读 · 0 评论 -
《深入理解JAVA虚拟机》9.类加载及执行子系统的案例与实践
一、Tomcat:正统的类加载器架构 从图中的委派关系中可以看出: CommonClassLoader能加载的类都可以被Catalina ClassLoader和SharedClassLoader使用,从而实现了公有类库的共用。 CatalinaClassLoader和Shared ClassLoader自己能加载的类则与对方相互隔离。 WebAppClassLoader可以使用SharedClassLoader加载到的类,但各个WebAppClassLoader实例之间相互原创 2020-05-13 09:11:41 · 174 阅读 · 0 评论 -
《深入理解JAVA虚拟机》7.虚拟机类加载机制
一、类加载的时机 类的生命周期,如下 何时需要进行类加载: 遇到new、getstatic、putstatic、invokestatic字节码指令。 使用java.lang.reflect包方法对类反射调用。 初始化一个类,其父类未初始化时。 虚拟机启动时,需要执行一个main方法,那么需要初始化该类。 jdk1.7动态语言支持时,当java.lang.invoke.MethodHandle实例最后的解析结果为REF_getStatic、REF_p.原创 2020-05-13 09:09:40 · 129 阅读 · 0 评论 -
《深入理解JAVA虚拟机》3.垃圾收集器与内存分配策略
哪些内存需要回收? 什么时候回收? 如何回收? 一、对象已死 1.引用计数算法 为对象添加一个引用计数器,一个地方引用,计数器加1,引用失效则减1,当计数器为0是,该对象将不再使用。该算法存在孤岛问题(循环依赖)。如下图,A对象与B对象,计数器均为1,但是已经废弃,通过该算法无法回收。 2.可达性分析算法 从GC Roots出发,向下搜索,所有走过的路径成为引用链(Reference Chain),当一个对象到GC Roots没有...原创 2020-05-13 09:08:21 · 205 阅读 · 0 评论 -
《深入理解JAVA虚拟机》2.Java内存区域与内存溢出问题
一、运行时数据区域 程序计数器:当前线程所执行的字节码的行号。 Java虚拟机栈:每个方法在执行的时候都会创建一个栈帧,存储局部变量表。操作数栈、动态链接、方法出口。 本地方法栈:为虚拟机使用到的Native方法服务。 Java堆:所有线程共享的内存区域,存放对象实例。 元空间( 方法区 ):存放类信息、常量、静态变量、即时编译器编译后的代码。别名Non-Heap非堆。 运行时常量池:是方法区的一部分。 直接内存:NIO中的channel与buffer可通过Native函数职级分配堆外内存,.原创 2020-05-13 09:06:13 · 99 阅读 · 0 评论 -
《Java并发编程实战》4.高级主题
十三、显式锁 1)Lock与ReentrantLock void lock(); 获取锁,未获取到则阻塞。 void lockInterruptibly() throws InterruptedException;获取锁,未获取到则阻塞,阻塞可中断。 boolean tryLock();获取锁,返回是否获取到 boolean tryLock(long time, TimeUnit unit) throws InterruptedException;获取锁,不能立即...原创 2020-05-11 11:24:46 · 112 阅读 · 0 评论 -
《Java并发编程实战》3.活跃性、性能与测试
十、避免活跃性危险 1)死锁 死锁的产生:A线程持有锁1,尝试获取锁2,同时B线程持有锁2,尝试获取锁1。 避免死锁:使用支持定时的锁;控制锁顺序;多个锁转为1个锁。jstack -l pid可查看死锁。 2)饥饿:某个线程一直获取不到它所需要的资源,导致线程饥饿。常见的是cpu饥饿,一般不设置线程的优先级(因为本身也不是很靠谱)。 3)活锁:因为某些原因导致线程一直执行一个重复的操作。例如MQ的消费消息失败导致消息放回了MQ,然后又被消费到,如此循环。可以适当设置重试策略防止这种...原创 2020-05-11 11:23:27 · 103 阅读 · 0 评论 -
《Java并发编程实战》2.结构化并发应用程序
六、任务执行 Executor框架 1)线程池 newSingleThreadExecutor 一个线程 newFixedThreadPool 固定大小线程池 newCachedThreadPool 缓冲线程池 newScheduledThreadPool 延迟或定时线程池 2)Executor生命周期 ExecutorService继承了Executor,扩展了其生命周期的管理方法。其生命周期状...原创 2020-05-11 11:22:28 · 107 阅读 · 0 评论 -
《Java并发编程实战》1.基础知识
二、什么是线程安全 当多个线程访问某个类时,不管运行时采用的何种调度方式或者这些线程如何交替执行,并且再主调度代码也不需要任何额外的同步或者协同,这个类能表现出正确的行为,那么这个类就是线程安全的。 三、对象共享 线程封闭 栈封闭:栈封闭中,只能通过局部变量才能访问对象。 ThreadLocal类:使用ThreadLocal存储变量。 只读共享 不可变:对象不能修改,对象的所有域是final,对象创建时没有逸出。 线程安全共享 ...原创 2020-05-11 11:21:30 · 113 阅读 · 0 评论