唐伯虎点蚊香dw
这个作者很懒,什么都没留下…
展开
-
WebRTC笔记
也就是媒体数据包将先从一端的浏览器流向Web服务器,再流向另一端的浏览器,这样web服务器将需要处理额外的流量,高清视屏可占用大量带宽,限制了体系结构的可扩展性。提议/应答协商: 要在双方之间建立媒体会话,必须在二者之间协商会话,之所以如此,是因为双方需要为会话确定一组通用的功能特性,这组功能特性事先并不明确,因为它取决于双方使用的具体浏览器版本,浏览器上运行的js以及用户双方各自的选择。对于从STUN服务器获取的这一IP地址,将与另一端的浏览器所共享,此地址将成为潜在的候选地址。原创 2024-06-21 16:07:22 · 151 阅读 · 0 评论 -
基于Raft解决“幽灵复现”问题
假设C成为leader后,Leader运行过程中会进行副本的修复,对于A来说,就是从log index为6的位置开始,C将会把自己的index为6及以后的log entry复制给A,因此A原来的index 6-10的日志删除,并保持与C一致。首先,我们聊一下Raft的日志恢复,在 Raft 中,每次选举出来的Leader一定包含已经Committed的数据(抽屉原理,选举出来的Leader是多数中数据最新的,一定包含已经在多数节点上Commit的数据),新的Leader将会覆盖其他节点上不一致的数据。原创 2023-10-25 09:19:18 · 177 阅读 · 0 评论 -
Raft 的 Figure 8 讲了什么问题?为什么需要 no-op 日志?
具体流程是在 Leader 刚选举成功的时候,立即追加一条 no-op 日志,并立即复制到其它节点,no-op 日志一经提交,Leader 前面那些未提交的日志全部间接提交,问题就解决了。那这里不就阻塞了吗?,Leader 查到日志有记录但又不能回复 1 给客户端(因为按照约束这条日志未提交),线性一致性要求不能返回陈旧的数据,Leader 迫切地需要知道这条日志到底能不能提交。只有等到新的请求进来,超过半数节点复制了 1-3-5 后,term=3 的日志才能跟着 term=5 的一起提交。转载 2023-10-25 08:44:56 · 179 阅读 · 0 评论 -
HTTPS 加密全过程
加密协议以前是SSL,现在都是TLS, 而证书现在大多数都是SSL证书。原创 2023-10-11 22:15:48 · 1035 阅读 · 0 评论 -
SSTables和LSM-Tree
LSM-Tree是基于SSTables的:在内存中维护两个Tree(交替工作),当Tree的大小达到一定的阈值之后,写操作转移到另一个tree,并将当前tree写入磁盘,形成一个SSTables实例,当读的时候,先从内存实例中查找,然后依次从磁盘的SSTables查找,并且写的时候为了避免宕机,会先写一个顺序预写日志(这也是Rockes和Level-DB的视线)原创 2023-09-12 10:16:33 · 297 阅读 · 0 评论 -
Eureka配置
【代码】Eureka配置。原创 2023-08-16 11:28:11 · 159 阅读 · 0 评论 -
docker-compose部署Redis主从+哨兵
这里分别起了三个Redis实例和三个哨兵实例,实测数据同步和master挂了之后slave自动成为master通过,这里需要注意的是,command 为覆盖dockerfile里面的command命令,在redis:4的dockerfile中启动命令为执行脚本: /usr/local/bin/docker-entrypoint.sh 但是不好传递参数,所以我们使用了覆盖的方式。3. redis-slave2.conf: redis slave2 的配置文件:内容同上。原创 2023-06-28 14:08:21 · 339 阅读 · 0 评论 -
Kafka学习笔记
4. 如果产生了消息积压,或者是吞吐量不够,可以通过增加主题的分区来解决,但是分区也不是越多越好,如果超过了一定的阈值,可能会导致不升反降,所以需要对硬件资源做一个吞吐量的测试,来找到一个合适的分区阈值区间,分区数过多也可能会导致leader宕机的时候不可用时间变得很长(选主过程)在均衡也可能会导致消息的重复消费。4. 可以根据seek方法进行消息回溯。1. kafka可以配置自动创建主题,如果收到一个未创建的主题消息,会自动创建默认分区数,默认副本数的主题,但是不推荐,推荐使用脚本创建。原创 2023-06-07 10:11:48 · 605 阅读 · 0 评论 -
Hive和Hadoop
原创 2023-04-02 23:09:11 · 91 阅读 · 0 评论 -
Swarm网络分析(2)
那么这里的ingress网络,是一个overlay网络,overlay是一个覆盖网络,基于linux的vxlan在三层网络上组成的二层网络,我们看到docker_gwbridge的驱动是local,也就是说他是一个本地的网络设备,可以看到,他的网段是10.255.0.0/16而接入他的有两个容器,一个是ingress-box,一个是web.2的一个容器,他的ip是10.255.0.8,下面的peers是集群的所有节点。原创 2023-03-12 12:42:35 · 324 阅读 · 0 评论 -
Sofa-jraft的Rpc调用客户端分析
也就是说BoltRpcClient的大部分操作其实是通过RpcClinet来完成的,在创建rpcclient之后调用了init然后创建了rpc的线程池,我们看下init方法。startup主要的部分就是设置了链接管理器,这里的链接管理器配置了ConnectionFactory,这个就是具体生产连接的,后面看。父类是AbstractClientService:实现对链接的管理的实现,以及请求发送的方法实现,实现接口ClientService: 定义链接,链接检查,断连,以及发送请求的方法。原创 2023-02-23 18:34:36 · 376 阅读 · 0 评论 -
Sofa-jraft的Rpc调用服务端分析
初始化了连接事件监听器,这个里面就是一个map,然后可以添加事件监听的处理器,初始化userProcessors, codec 是一个编码和解码器的工厂,可以获取编码器和解码器,然后他调用了父类的构造器super(port);解码器的流程是,先解析出协议的版本,将协议code写入channel的attribute,然后重置读指针,获取版本对应的解码器进行解码,而解码的流程也比较简单,逐个获取各个数据,根据长度将数据填入对象中。原创 2023-02-22 17:34:16 · 529 阅读 · 0 评论 -
Kafka的日志同步
上图中,如果此时三个副本都在ISR集合中,那么此时他们的LEO,分别为9,7,6 ,而HW则为6,只有在HW之前的消息才是消费者可见的。现在,生产者一直往leader(带阴影的方框)写入消息,某一时刻,leader的LEO增加至5,并且所有副本的HW都还为0。fllower副本收到leader副本返回的拉取结果,将消息追加到本地日志中,并更新日志的偏移量信息。leader副本所在的服务器读取本地日志,并更新对应拉取的follower副本的信息。这个过程中,我们分析下LEO和HW的变化。原创 2023-02-16 14:31:23 · 372 阅读 · 0 评论 -
K8s为何需要Pod
不过这里的war包容器不是一个普通的容器,而是一个Init Container类型的容器,在Pod中,Init container定义的容器,都会比spec.container定义的用户容器先启动,并且Init Container容器会按顺序逐一启动,知道他们都启动退出了,用户容器才启动,这里war包容器启动后将war包拷贝到一个目录下,然后tomcat容器共享同一目录,就可以获取到这个war包了,而这里Init Container容器就扮演了一个sidecar的角色。二,统一Pod中容器的关系。原创 2022-11-17 15:31:57 · 473 阅读 · 0 评论 -
容器网络原理
我们创建了一个veth-pair设备后,我们两端分别有两个网段的ip,我们从ip1ping到ip2的时候,如果没有相应的路由规则,那么主机会不知道该吧包发送到哪个设备,我们创建路由后协议栈就知道该发往veth-pair设备,但是发送后vethpair需要目的地的mac地址,我们的ip2收到arp请求之后,回复mac地址,但是它回复的请求也不知道该发送到哪个设备,所以也需要创建路由来匹配。calico是通过配置路由规则来实现一个不同主机间的通信,他的优势是没有封包解包,比较高效。......原创 2022-07-21 17:17:53 · 473 阅读 · 0 评论 -
K8S笔记之Pod思想
举例说明:War包与Web服务器现在有—个JavaWeb应用的WAR包’它需要放在TOmcat的webapps目录下运行°假如只能用Docker来做这件事’那该如何处理这个组合关系呢?第一种方法是把WAR包直接放在TOmcat镜像的webapps目录下’做成_个新的镜像运行起来。可是’这时如果要更新WAR包的内容’或者要升级Tomcat镜像’就需要重新制作—个新的发布镜像,非常麻烦°另一种方法是压根儿不管WAR包’永远只发布一个TOmcat容器。不过’这个容器的webapps目录必须声明—个ho原创 2022-07-11 17:40:58 · 423 阅读 · 1 评论 -
K8S笔记只Pod讲解
Pod:Pod是一个逻辑概念,也就是说,K8s真正处理的还是宿主机操作系统上Linux容器的Namespace和Cgroups,并不存在所谓的Pod的边界或者隔离环境, 具体的说,Pod里的所有容器都共享一个Network Namespace,并且可以声明共享同一个Volume,具体做法是,Pod需要使用一个中间容器,叫做Infra容器。这个Pod中 Infra容器永远是第一个被创建的容器,用户定义的其他容器则通过Join Network Namespace的方式与Infra容器关联再一起,这个I原创 2022-07-11 17:12:51 · 234 阅读 · 0 评论 -
Mysql间隙锁
Mysql的间隙锁是为了在RR级别解决幻读问题而引入的,间隙锁是gap lock ,而mysql 用的是间隙锁和gap锁的结合,也就是next-key lock,而在不同的索引上,mysql加锁的方式也不一样:唯一索引上:如果条件为=5 ,间隙锁退化为行锁,也就是只会锁住条件中的那一行对象,如果是>5,则会添加一个[5, ∞) 的一个next-key锁,5这个行锁和(5,∞)这个间隙锁普通索引上:如果条件为5,那么mysql会通过5查询左右两边的一个间隙,也就是比5小的第一个值和比5大的第一个值,然原创 2022-06-28 18:06:05 · 5531 阅读 · 3 评论 -
关于用户消息的推送
遇到一个面试题:需要向所有用户推送一个活动消息,比如618大促,每个用户收到消息后进行展示 ,一般是右上角的铃铛显示未读消息。这种场景一般情况下回选择使用kafka来进行消息推送,如果有千万个用户,那么为每个用户推送一条消息,或者是一条消息,为每个用户绑定一个关系表,用户读取后,消息提示消息,这种情况下,推送一条消息就会生成千万条数据,有没有更好的方法呢。可以利用kafka的offset思想,每个用户保存一个offset,通过offset来进行消息的消费读取,这样kafka只存在一条消息,但是每个用户都可以原创 2022-06-07 09:42:04 · 364 阅读 · 0 评论 -
基于数组实现定长队列
有时候我们需要一个定长的队列,超过的数据会挤掉最先添加的数据这里提供一个技术数组实现/*** * data format of offset+separator+operation+separator+identify+separator+key+separator+dataSerial+endMark * */public class RaftLeaderAppendData implements FixedLengthStoreQueue{ private Integer a原创 2022-04-07 15:55:40 · 422 阅读 · 0 评论 -
SpringCloud-gateway 实现服务发现路由
springcloud-gateway使用webflux响应式编程并使用Netty非Servlet容器,使用Netty转发请求,属于非阻塞请求,具有很高的性能自定义服务发现路由配置目前有个难题是,我们的项目都是带有上下文的,并且上下文与服务id保持一致,所以请求的时候都是服务/serviceId/api/test,但是gateway自带的服务发现路由配置默认是去掉serviceId的,并且不具备扩展的能力package org.springframework.cloud.gateway.d.原创 2022-03-31 10:30:35 · 1689 阅读 · 2 评论 -
JVM设计与实现-底层原理
摘自虚拟机设计与实现 6.1 什么是线程由于线程支持多个层级,当讨论到一个线程时,应该指出它位于哪个层级上,一个层级上的单个线程可能包含更高级上的多个线程现实中没有必要构造太多层级的线程,通常不超过3级。第二级共享第1级的硬件上下文,第3级共享第二级的软件上下文在Linux设计中,内核线程(软件线程)以M:N映射复用硬件上下文,glibc的用户线程以1:1映射使用内核线程上下文。有些系统在用户线程和内核线程之间使用M:N或者M:1映射,比如GNU Portable Threads 和Windows F原创 2022-03-28 16:53:50 · 1710 阅读 · 0 评论 -
Linux中文件的访问方式
Linux访问文件的模式:1.规范模式: 规范模式下打开文件后,标志O_SYNC与O_DIRECT清零,而且他的内容是由系统调用read()和write()来存取。系统调用read将阻塞调用进程,直到数据被拷贝到用户态地址空间(内核允许返回的字节数小于要求的字节数)。但系统调用write()不同,它在数据被拷贝到页高速缓存(延迟写)后就马上结束。2.同步模式 同步模式下打开文件后,标志O_SYNC置为1或稍后由系统调用fcntl()对其置1。这个标志只影响写操作(读操作总是会阻塞),...原创 2022-03-16 14:50:09 · 1434 阅读 · 0 评论 -
Unsafe中putObjectVolatile和putOrderedObject的区别
首先在上述Unsafe几个方法的源代码中,可以看到有write_barrier和read_barrier这两个内存屏障,这两个就是对应的硬件中的写屏障和读屏障,java内存模型中使用的所谓的LoadLoad、LoadStore、StoreStore、StoreLoad这几个屏障就是基于这两个屏障实现的写屏障的作用就是禁止了指令的重排序,并且配合C语言中的volatile关键字(C中的volatile关键字只能保证可见性不能保证有序性),通过添加内存屏障+C中的Volatile实现了类似Java.原创 2022-02-18 10:14:52 · 1764 阅读 · 2 评论 -
深入Linux内核架构笔记(页缓存和块缓存)
缓存是页交换或调页操作的逆操作(换页的相关信息,在第18章讨论)。尽管缓存牺牲了物理内 存(使得不需要在块设备上进行低速操作),而实现页交换时,则是用低速的块设备来代替物理内存。 因而内核必须尽力同时考虑到这两种机制,确保一种方法带来的好处不会被另一种方法的不利之处抵 消,这不是件容易事。slab缓存是一个内存到内存的缓存, 其目的不是加速对低速设备的操作,而是对现存资源进行更简单、更高效的使用。dentry缓存也用于 减少对低速块设备的访问,但它无法推广到通用场合,因为它是专门用于处理单一数据类型的。原创 2022-01-28 18:13:52 · 2969 阅读 · 0 评论 -
深入Linux内核架构笔记(同步)
内核可以不受限制地访问整个地址空间。在多处理器系统上(或类似地,在启用了内核抢占的单 处理器系统上,可参见第2章),这会引起一些问题。如果几个处理器同时处于核心态,则理论上它们可以同时访问同一个数据结构内核为此提供了各种锁选项,分别优化不同的内核数据使用模式。 原子操作:这些是最简单的锁操作。它们保证简单的操作,诸如计数器加1之类,可以不中断 地原子执行。即使操作由几个汇编语句组成,也可以保证。 自旋锁:这些是最常用的锁选项。它们用于短期保护某段代码,以防止其他处理器的访问。 在内核等待自旋原创 2022-01-28 11:48:54 · 2678 阅读 · 0 评论 -
深入Linux内核架构笔记(缺页异常)
在实际需要某个虚拟内存区域的数据之前,虚拟和物理内存之间的关联不会建立。如果进程访问 的虚拟地址空间部分尚未与页帧关联,处理器自动地引发一个缺页异常,内核必须处理此异常。这是 内存管理中最重要、最复杂的方面之一,因为必须考虑到无数的细节。例如,内核必须确定以下情况。 缺页异常是由于访问用户地址空间中的有效地址而引起,还是应用程序试图访问内核的受保 护区域? 目标地址对应于某个现存的映射吗? 获取该区域的数据,需要使用何种机制?缺页处理的实现因处理器的不同而有所不同。由于CPU采用了不同原创 2022-01-28 10:57:33 · 2210 阅读 · 1 评论 -
深入Linux内核架构笔记(进程空间堆管理)
堆是进程中用于动态分配变量和数据的内存区域,堆的管理对应用程序员不是直接可见的。因为 它依赖标准库提供的各个辅助函数(其中最重要的是malloc)来分配任意长度的内存区。malloc和 内核之间的经典接口是brk系统调用,负责扩展/收缩堆。新近的malloc实现(诸如GNU标准库提供的) 使用了一种组合方法,使用brk和匿名映射。该方法提供了更好的性能,而且在分配较大的内存区时 具有某些优点brk系统调用只需要一个参数,用于指定堆在虚拟地址空间中新的结束地址(如果堆将要收缩, 当然可以小于当前值)。 照原创 2022-01-28 10:34:14 · 1610 阅读 · 0 评论 -
深入Linux内核架构笔记(进程虚拟内存)
在32位架构中,进程的虚拟地址按照3:1的比例划分为内核空间和用户空间,这样划分是为了实现CPU的不同权限,而64位架构中,因为进程的虚拟地址足够大,所以没有这个划分,都是足够的,一般是1:1,高位作为内核空间,地位作为用户空间,虽然64位的系统寻址可以达到很大,但是实际的CPU硬件的寻址并没有那么大,目前一般只有48根地址先,也就是可以256T这么大,那么高位的128T作为内核空间,地位的128T作为用户空间,中间的一部分作为不可用部分,这个通过地址空间的转换来实现的,具体参考前面的文章而用户空间原创 2022-01-27 18:36:36 · 1093 阅读 · 0 评论 -
深入Linux架构笔记(内存管理)
内核初始化期间由初始化内存分配器分配内存,完成后内存分配工作交给伙伴系统基于伙伴系统的内存管理专注于某个结点的某个内存域,例如,DMA或高端内存域。但所有内存域和结点的伙伴系统都通过备用分配列表连接起来也就是说内存的每个区域都有自己的伙伴系统,并且通过备用列表连接起来,比如分配普通区域内存是,伙伴系统分配失败,就使用DMA区域的伙伴系统分配内存内存的碎片处理:用户空间应用程序的内存一般通过页表映射,所以碎片问题一般只涉及到内核很长时间以来,物理内存的碎片确实是Linux的弱点之一。尽管已经提出了许原创 2022-01-27 14:49:40 · 717 阅读 · 0 评论 -
Linux Native AIO
首先声明一下epoll+nonblock从宏观角度可以叫做全异步,但从微观的角度来看还是同步的IO。只是在数据到达后得到系统通知,然后同步执行recv取回数据,没有iowait。真正的异步IO(下面会统一叫做AIO)应该像Windows IOCP一样,传入文件句柄,缓存区,尺寸等参数和一个函数指针,当操作系统真正完成了IO操作,再执行对应的函数。实际上对于socket来说,epoll已经是最高效的模型了,虽然比AIO多一次recv系统调用,但总体来看没有任何IO等待,效率很高。而且epoll是天然.原创 2022-01-25 13:41:28 · 249 阅读 · 0 评论 -
mmap和page cache
进程调用mmap,内核做了哪些呢?建立进程虚拟地址空间与文件内容空间之间的映射 而后第一次读写mmap映射的内存时,由于页表并未与物理内存映射,触发缺页异常 缺页异常程序先根据要访问的偏移和大小从page cache中查询是否有该文件的缓存,如果找到就更新进程页表指向page cache那段物理内存 没找到就将文件从磁盘加载到内核page cache,然后再令进程的mmap虚拟地址的页表指向这段page cache中文件部分的物理内存所以结论是,内核会把文件读到page cache中。也只.原创 2022-01-24 16:38:54 · 1030 阅读 · 1 评论 -
Linux伙伴系统算法
伙伴系统算法:内核应该为分配一组连续的页框而建立一种健壮高效的分配策略。因此,必须解决著名的内存管理问题,也就是所谓的外碎片。频繁的请求和释放不同大小的一组连续页框, 必然导致在已分配页框的块内分散了许多小块的空闲页框。因此带来的问题是,即使有足够的空闲页框可以满足请求,但要分配一个大块的连续页框就无法满足。从本质上说,避免外碎片的方法有两种: 1.利用分页单元吧一组非连续的空闲页框映射到连续的线性地址区间 2.开发一种适当的技术来记录现存的空闲连续页框块的情况,以尽量...原创 2022-01-13 17:45:11 · 580 阅读 · 0 评论 -
volatile,指令重排和内存屏障
volatile我们已经再熟悉不过了,他保证了属性的可见性并且禁止指令重排对于可见性:也就是一个线程改了值,另外一个线程可以立马看到结果,也就是但操作是原子的对于指令重排,有两种:一种是编译重排,一种是CPU重排(运行期重排),编译重排这里的编译不是变成橙字节码,而是JVM解释成字节码的时候的重排,那么这两种重排都会有一些保证:编译器重排有一些happenbefore规则,在不违反这些原则的基础上进行重排,而有一些指令他是在编译期间就能知道顺序的,比如说new Object()操作包含以下几步:原创 2022-01-09 22:34:33 · 829 阅读 · 0 评论 -
深入理解Linux内核笔记(关于上下文切换)
进程上下文切换:硬件上下文:CPU核心的寄存器数据, 在Linux中硬件上下文一部分放在TSS段(内存中的一段空间),一部分放在内核态堆栈中thread:因为进程不把硬件上下文保存在TSS中,而是保存在这个类型为thread_struct的thread字段中,这里包含大部分CPU寄存器的值, 但不包括一些通用寄存器,他们的值保留在内核堆栈中Linux调度程序调度进程的过程:首先如果调度程序决定要把CPU交个某个进程,那么开始进行进程切换: 1.吧进程描述符thread字段的值...原创 2022-01-07 18:09:19 · 568 阅读 · 0 评论 -
CPU的缓存一致性协议与Volatile
我们都知道CPU有三级缓存,L1,L2,为核心独享,L3为CPU共享,而当前主流的CPU还都支持Store Buffer 和invalid queue,在这种情况下MESI是无法生效的,而在一些指令重排的情况下,核心读到的值可能不是最新的,这时就需要通过指令重排来进行同步,指令重排不止具备禁止重排序的特性,还具备同步刷新的特性volatile是JVM的内存语义,这里借用知乎中的一个回答:volatile是java语言层面给出的保证,MSEI协议是多核cpu保证cache一致性的一种方法,中间隔的还很原创 2022-01-04 11:06:04 · 634 阅读 · 0 评论 -
java实现快速排序
private static void quickSort(int[] arr , int start ,int end){ /**定义一个终止的条件*/ if(start >= end){ return ; } /** 在这里的i我们必须从start开始,因为,如果数组本来就是有序的, * 那么一圈下来,还是会做一个交换,如果从i+1开始,那么最后将会导致本来有序的数组变成了无序**/ .原创 2021-12-29 18:27:09 · 202 阅读 · 0 评论 -
堆排序Java实现以及使用场景
堆排序是基于大小堆来实现的,利用数组中左右子树的数学规律来进行构建最大树或者是最小树,在这基础上将最大数或者是最小树下沉,并将树的长度减1,直到树的长度为1,最后数组即为排序后的数组场景:跟快排一样是一个O(nLogn)的算法,但是在堆排序中有较多次数的交换,所以总体来说,是比不上快排的,但是如果你需要的不是整个排序,而是最大或者是最小的一部分,那么堆排序就具有很大优势了实现:private static void heapSort(int[] arrays){ buildMa原创 2021-12-29 16:34:37 · 676 阅读 · 0 评论 -
java实现超时任务
有时候碰到一种情况,远程请求一个任务,但是请求时间不能超过一定时间,超过后按超时处理,这种情况我们可以用一段代码来实现,但是如果我们实现成一个类 ,则可以让代码更简洁,更具有健壮性首先定义一个接口public interface TimeOut<T> extends Callable<T> { void onTimeout(); void start();}start方法表示开始这个任务,onTimeout方法超时后的动作,该接口继承了Callab原创 2021-12-15 18:18:46 · 2341 阅读 · 0 评论 -
Raft集群流程
一 ,启动后1.每个节点都有一个集群的配置,配置了集群所有节点的ip和端口 扩展点:可以动态的增加集群节点并写入到配置2.启动后节点监听一个端口,并启动一个客户端,随机连接一个节点,获取Leader信息 a.如果对方节点还没有领导者,并且不在选举状态,则当前节点发起选举 b.如果对方节点回复整个集群正在进行选举,则不做任何动作,等待选举出来的领导者链接 c.如果集群已经存在领导者,则返回领导者的ip和端口信息,返回后,发送连接设...原创 2021-12-13 16:29:17 · 2130 阅读 · 2 评论