碎片化学习
虚拟内存技术
是指:当进程运行时,先将其中一部分装入内存,另一部分暂留在磁盘,当要执行的指令或访问的数据不在内存时,由操作系统自动完成将他们从磁盘调入内存的工作。
进程和线程从寻址上的区别:
https://cloud.tencent.com/developer/article/1462022
每个线程都有自己的堆栈空间,但是线程堆栈的地址是按照进程地址空间统一编址的,所以每个线程堆栈地址空间是不会重复的,
TCP和UDP区别:
https://www.bilibili.com/video/av59530395/?spm_id_from=333.788.videocard.10
https://blog.csdn.net/sifanchao/article/details/82285018
TCP粘包,拆包及解决方法、丢包的原因及解决办法:https://blog.csdn.net/ldw662523/article/details/79565797
粘包问题的解决策略
由于底层的TCP无法理解上层的业务数据,所以在底层是无法保证数据包不被拆分和重组的,这个问题只能通过上层的应用协议栈设计来解决,根据业界的主流协议的解决方案,可以归纳如下。
(1)消息定长,例如每个报文的大小为固定长度200字节,如果不够,空位补空格;
(2)在包尾增加回车换行符进行分割,例如FTP协议;
(3)将消息分为消息头和消息体,消息头中包含表示消息总长度(或者消息体长度)的字段,通常设计思路为消息头的第一个字段使用int32来表示消息的总长度;
网络模型:
=================================java===================================
Servlet:http://c.biancheng.net/view/3980.html
jvm内存模型
栈:程序运行临时变量
堆:存放的都是对象的实例,垃圾回收主要回收的就是堆区。为了提升垃圾回收的性能,又把堆分成两块区新生代(young)和年老代(old)
本地方法栈:系统底层的方法
程序计数器:记录当前线程执行程序的位置
方法区(元空间):运行时的常量池static、classloader
栈、本地方法栈、程序计数器都是线程私有的;
堆是被所有线程共享的区域
方法区是被所有线程共享区域,用于存放已被虚拟机加载的类信息,常量,静态变量等数据。也叫永久代
GC
判断是否被删除:GCRoot查找栈、本地栈、方法区是否有使用,如果被删除标记(标记清理,会产生碎片,所以有了标记整理,但是代价比较大)
删除进行复制到另一个区,把新生代复制到幸存区,如果在新生代和幸存区6次都没有被gc掉就存到old区,fullgc会到导致程序停掉
类加载机制
加载:jvm把class文件加载到内存并在方法区创建clss对象
验证:验证是否符合jvm规范/代码逻辑校验
准备:为类变量(static 修饰的)分配内存并初始化
解析:主要任务是将其在常量池中的符号引用替换成直接其在内存中的直接引用
初始化:JVM 会根据语句执行顺序对类对象进行初始化:
使用new关键字实例化对象的时候、读取或设置一个类的静态字段(被final修饰、已在编译器把结果放入常量池的静态字段除外)的时候,以及调用一个类的静态方法的时候
使用 java.lang.reflect 包的方法对类进行反射调用的时候
当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化。
当虚拟机启动时,用户需要指定一个要执行的主类(包含main()方法的那个类),虚拟机会先初始化这个主类
使用:当 JVM 完成初始化阶段之后,JVM 便开始从入口方法开始执行用户的程序代码
卸载:当用户程序代码执行完毕后,JVM 便开始销毁创建的 Class 对象,最后负责运行的 JVM 也退出内存。这个阶段也只是了解一下就可以。
NIO:
核心组件:
通道(Channel)
缓冲区(Buffer)
选择器(Selector)
https://blog.csdn.net/u013857458/article/details/82424104
Java中异常:
final修饰类:不可以被继承
方法:不可以被重写
变量:不可以重新赋值
为什么用final:一般都是一些固定行为和值,不希望被修改否则可能会影响程序的健壮性
finalize(已被弃用):定义在object中,垃圾回收前调用,在对象回收前释放资源,每个对象的finalize方法只会被调用一次
finalize生命周期:不会及时回收原因是将不可达对象放入到一个队列,然后用一个低优先级的线程回收,可能会造成死锁
HashMap:
因为put扩容,所以是非线程安全的
jdk8:数组+链表+红黑树,为何优化:优化检索性能,链表需要遍历,红黑树判断后,取左边树还是右边树
HashTable对get和put都会上锁,ConcurrentHashMap只对put加锁
java动态代理:如果有接口类型继承默认使用 java动态代理,
CGLIB代理:如果指定了@EnableAspectJAutoProxy(proxyTargetClass=True)则使用CGLIB代理
========java死锁排查==========
jstack\idea中的有个快照
=====================spring==========================
是一个开源的Java EE开发框架。核心功能是IOC和AOP,使得Java EE应用程序的开发更加简捷,通过使用POJO为基础的编程模型促进良好的编程风格。
IOC容器底层是:map
轻量级;
ioc
使用控制反转技术实现了松耦合。依赖被注入到对象,而不是创建或寻找依赖对象。
aop
@aspect @pintcut
通常说是面向切面编程,就是将这些横切关注的点与业务逻辑分开。
日志、权限
原理:
容器:Spring包含并管理应用程序对象的配置及生命周期。
spring bean的生命周期:
- 实例化 Instantiation
- 属性赋值 Populate
- 初始化 Initialization
- 销毁 Destruction
https://www.jianshu.com/p/1dec08d290c1
spring bean 作用域:
singleton 在spring IoC容器仅存在一个Bean实例,Bean以单例方式存在,bean作用域范围的默认值。
prototype 每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时,相当于执行newXxxBean()。
request 每次HTTP请求都会创建一个新的Bean,该作用域仅适用于web的Spring WebApplicationContext环境。
session 同一个HTTP Session共享一个Bean,不同Session使用不同的Bean。该作用域仅适用于web的Spring WebApplicationContext环境。
application 限定一个Bean的作用域为ServletContext的生命周期。该作用域仅适用于web的Spring WebApplicationContext环境。
==================mybitas====================
其实就是一个orm框架,内部封装了jdbc。使用xml和注解将pojo与数据记录进行映射。
优点:
使用原生sql,性能高、灵活度高;
相对与jdbc减少了代码量,解除了sql和代码的耦合便于统一管理。
支持对象与数据库的ORM字段关系映射
缺点:
SQL语句的编写工作量较大,尤其是字段多、关联表多时,更是如此
SQL语句依赖于数据库,导致数据库移植性差,不能随意更换数据库。
#{}是预编译处理,Mybaties的占位符,可以用来防止sql注入,具体原理是,mybaties在创建prepareStatement时,
会用?来替换#{},然后在指向SQL语句前,通过反射的方式在statement里set相应的参数。
DAO的原理是什么
DAO接口就是Mapper接口,接口的全限定名,就是映射文件的namespace的值;接口的方法名,就是映射文件中Mapper的Statement的id值;
接口方法内的参数,就是传递给SQL的参数。Mapper接口里面的方法是不能重载的,因为使用全限定名+方法名的保存和寻找策略。
Mapper接口的工作原理,是使用JDK动态代理,Mybatis运行时会使用JDK动态代理为Mapper接口生成代理对象proxy,代理对象会拦截接口方法,
执行MapperStatement的SQL,然后将SQL执行结果返回。
分页
Mybatis使用RowBounds对象进行分页,针对ResultSet结果集执行内存分页,不是物理分页。
可以在SQL内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件完成物理分页。
标签
<select>,<update>,<insert>,<delete>,<resultMap>,<parameterMap>,<sql>,<include>,<selectKey>,和动态标签。
有9种动态标签:trim|where|set|foreach|if|choose|when|otherwise|bind;
Mybatis的批量执行
foreach标签,foreach主要用在构建in条件中,可以在SQL中进行迭代一个集合。
foreach元素的属性主要有item,index,collection,open,separator,close。
一对一查询:
一对多查询有联合查询和前台查询:
联合查询是在resultMap里面配置collection节点配置一对一的类
嵌套查询是先查一个表,根据这个表里面的结果的外键id,再去另外一个表查询,也通过collection配置,
但另外一个表的查询通过select属性配置。
Mybatis的延迟加载
Mybatis仅支持associate关联对象和collection关联集合对象的延迟加载。在Mybatis的配置文件中,可以配置是否启动延迟加载:
lazyLoadingEnabled=true|false。
原理是,使用CGLIB创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用a.getB().getName(),
拦截器invoke()方法发现a.getB()是null值,那么就会单独发送事先保存好的查询关联B对象的sql,把B查询上来,
然后调用a.setB(b),于是a的对象b属性就有值了,接着完成a.getB().getName()方法的调用。这就是延迟加载的基本原理。
获取自动生成的主键:userGeneratedKeys="true"
加载mapper的几种方式:
4种(按照优先级):packgage、url、resource、class
=======================springboot=======================
相比spring优点:
1、Spring Boot 可以帮助我们以最少的工作量,更加健壮地使用现有的 Spring功能。
2、使用 JavaConfig 有助于避免使用 XML。
3、封装了大量的starter开箱即用,避免大量的 Maven 导入和各种版本冲突。
4、提供自动装配,添加相关注解而无需xml配置即可自动加载对象并像以前一样对其进行管理。
配置文件方式及加载顺序:
properties 文件、YAML 文件、环境变量、系统参数和命令行选项参数
1、命令行指定的参数
2、系统环境变量
3、JAR包外面的配置文件参数(`application-{profile}.properties(YAML)`)
4、JAR包里面的配置文件参数(`application-{profile}.properties(YAML)`)
5、JAR包外面的配置文件参数(`application.properties(YAML)`)
6、JAR包里面的配置文件参数(`application.properties(YAML)`)
aop横切点:
Around、before、after、
https://blog.csdn.net/rainbow702/article/details/52185827
松绑定:配置属性键不需要与属性名完全匹配。可以用驼峰式、短横线式、或者下划线分割来命名
设计模式
工厂方法模式:FactoryBean
模板方法模式:JdbcTemplate
代理模式:AOP
静态代理的实现为每个实际对象都产生一个代理类,并将其作为内部属性。
这会导致类数量的急速增加,并且代理类的代码存在大量重复。这就需要动态代理来实现。
动态:通过jdk提供,需要实现InvocationHandler接口的invoke方法;通过字节码增强实现(CGLIB)
观察者模式:ApplicationListener事件监听机制
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
监听器、 日志收集、 短信通知、邮件通知
单例模式:Spring默认的创建Bean的作用域就是单例
https://www.cnblogs.com/aishangJava/p/10546741.html
===================springcloud=================
=========================redis=========================
redis线程模型:单线程、NIONIO(非阻塞)、异步事件模型
1、基于内存
2、单线程(不存在反复线程切换问题),采用epool实现IO多路复用,将连接信息和事件放到队列中,依次放到文件事件分派器,事件分派器将事件分发给事件处理器。
nginx也是采用IO多路复用原理解决C10K问题
持久话方式:
RDB持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘。也是默认的持久化方式,这种方式是就是将内存中数据以快照的方式写入到二进制文件中,默认的文件名为dump.rdb。
可以通过配置设置自动做快照持久化的方式。我们可以配置redis在n秒内如果超过m个key被修改就自动做快照,下面是默认的快照保存配置
redis会将每一个收到的写命令都通过write函数追加到文件中(默认是 appendonly.aof)
当redis重启时会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容。当然由于os会在内核中缓存 write做的修改,所以可能不是立即写到磁盘上。
这样aof方式的持久化也还是有可能会丢失部分修改。不过我们可以通过配置文件告诉redis我们想要 通过fsync函数强制os写入到磁盘的时机。有三种方式如下(默认是:每秒fsync一次)
redis调用fork ,现在有父子两个进程
子进程根据内存中的数据库快照,往临时文件中写入重建数据库状态的命令
父进程继续处理client请求,除了把写命令写入到原来的aof文件中。同时把收到的写命令缓存起来。这样就能保证如果子进程重写失败的话并不会出问题。
当子进程把快照内容写入已命令方式写到临时文件中后,子进程发信号通知父进程。然后父进程把缓存的写命令也写入到临时文件。
现在父进程可以使用临时文件替换老的aof文件,并重命名,后面收到的写命令也开始往新的aof文件中追加。
RDB AOF
占用存储空间: 小(数据级:压缩) 大(指令级:重写)
存储速度: 慢 快
恢复速度: 快 慢
数据安全性: 会丢失数据 依据策略决定
资源消耗: 高/重量级 低/轻量级
启动优先级: 低 高
https://www.jianshu.com/p/09964945e4fe
redis集群数据分片:
Redis 集群的数据分片是redis进行分布式存储的一种,它引入了hash槽的概念,每个redis节点存储一定范围的hash槽 ,redis集群有16384个hash槽,
每个key通过CRC16校验后对16384取模来决定存储在哪个槽哪个节点,新加入一个节点,16384/节点数=4096槽点,然后执行重新分配: ./redis-trib.rb reshard 127.0.0.1:6740
redis哨兵机制:
Redis Sentinel是Redis高可用的实现方案。Sentinel是一个管理多个Redis实例的工具,它可以实现对Redis的监控、通知、自动故障转移。
每个Sentinel节点都需要 定期执行 以下任务:
1、每个 Sentinel 以 每秒钟 一次的频率,向它所知的 主服务器、从服务器 以及其他 Sentinel 实例 发送一个 PING 命令。
2、如果一个 实例(instance)距离 最后一次 有效回复 PING 命令的时间超过 down-after-milliseconds 所指定的值,那么这个实例会被 Sentinel 标记为 主观下线。
3、如果一个 主服务器 被标记为 主观下线,那么正在 监视 这个 主服务器 的所有 Sentinel 节点,要以 每秒一次 的频率确认 主服务器 的确进入了 主观下线 状态。
4、如果一个 主服务器 被标记为 主观下线,并且有 足够数量 的 Sentinel(至少要达到 配置文件 指定的数量)在指定的 时间范围 内同意这一判断,那么这个 主服务器 被标记为 客观下线。
5、在一般情况下, 每个 Sentinel 会以每 10 秒一次的频率,向它已知的所有 主服务器 和 从服务器 发送 INFO 命令。
当一个 主服务器 被 Sentinel 标记为 客观下线 时,Sentinel 向 下线主服务器 的所有 从服务器 发送 INFO 命令的频率,会从 10 秒一次改为 每秒一次。
6、Sentinel 和其他 Sentinel 协商 主节点 的状态,如果 主节点 处于 SDOWN 状态,则投票自动选出新的 主节点。将剩余的 从节点 指向 新的主节点 进行 数据复制。
7、当没有足够数量的 Sentinel 同意 主服务器 下线时, 主服务器 的 客观下线状态 就会被移除。当 主服务器 重新向 Sentinel 的 PING 命令返回 有效回复 时,
主服务器 的 主观下线状态 就会被移除。
缓存雪崩:
缓存key在同一时间失效(缓存挂掉、过期),并同时请求到数据库
1、失效时间随机、避免同时失效
2、多级缓存,多一层保护
3、限流降低并发数量
4、
缓存击穿:缓存一定会请求到数据库
1、把击穿的请求内容缓存起来
2、布隆过滤器 gauva (google的)
缓存击穿:
查询一个数据库中不存在的数据,比如商品详情,查询一个不存在的ID,每次都会访问DB,如果有人恶意破坏,很可能直接对DB造成过大地压力。
缓存击穿的解决方案:
当通过某一个key去查询数据的时候,如果对应在数据库中的数据都不存在,我们将此key对应的value设置为一个默认的值,比如“NULL”,并设置一个缓存的失效时间,这时在缓存失效之前,所有通过此key的访问都被缓存挡住了。后面如果此key对应的数据在DB中存在时,缓存失效之后,通过此key再去访问数据,就能拿到新的value了。
缓存失效:
在高并发的环境下,如果此时key对应的缓存失效,此时有多个进程就会去同时去查询DB,然后再去同时设置缓存。这个时候如果这个key是系统中的热点key或者同时失效的数量比较多时,DB访问量会瞬间增大,造成过大的压力。
缓存失效的解决方案:
将系统中key的缓存失效时间均匀地错开,防止统一时间点有大量的key对应的缓存失效;
重新设计缓存的使用方式,当我们通过key去查询数据时,首先查询缓存,如果此时缓存中查询不到,就通过分布式锁进行加锁,取得锁的进程查DB并设置缓存,然后解锁;其他进程如果发现有锁就等待,然后等解锁后返回缓存数据或者再次查询DB。
热点key:
缓存中的某些Key(可能对应用与某个促销商品)对应的value存储在集群中一台机器,使得所有流量涌向同一机器,成为系统的瓶颈,该问题的挑战在于它无法通过增加机器容量来解决。
热点key的解决方案:
客户端热点key缓存:将热点key对应value并缓存在客户端本地,并且设置一个失效时间。对于每次读请求,将首先检查key是否存在于本地缓存中,如果存在则直接返回,如果不存在再去访问分布式缓存的机器。
将热点key分散为多个子key,然后存储到缓存集群的不同机器上,这些子key对应的value都和热点key是一样的。当通过热点key去查询数据时,通过某种hash算法随机选择一个子key,然后再去访问缓存机器,将热点分散到了多个子key上。
分布式锁
redis分布式锁注意问题:
1、锁失效时间设置多久合适,如果业务还未执行完毕锁失效了,其它并发线程会进来,大量并发的情况下可能导致锁永久失效
每个线程生成一个uuid,setnx(key,uuid,10),把当前锁与该线程关联起来,业务逻辑执行完成后判断该锁get(key)是不是==uuid,如果等于的话再释放锁
失效时间设置:可以采用一个timer,每间隔1/3的失效时间进行一次续命,重新加10s(比如10s失效,每隔3s)
redisson其实大致就是以上方案实现
当然还有个问题,master加锁成功,还没有同步到slaver,master宕机了重新选举了master,此时锁失效,
这种情况可以采用zk解决,zk也是主从怎么不存在这个问题呢?
主要zk能高度保证数据的一致性(paxos算法选举,少数服从多数):create request进来到leader,它会先生成log文件,然后再通知follower节点,
follower节点收到通知也同样优先生成log文件,然后ack到leader,当leader收到半数以上的follower节点的ack消息就
开始commit(两阶段提交)
幂等:可能你要对一个事情进行操作,这个操作可能会执行成百上千次,但是操作结果都是相同的,这就是幂等性。
解决幂等性:
可以参考数据库乐观锁机制,比如执行一条更新库存的 SQL 语句,在并发场景,为了性能和数据可靠性,会在更新时加上查询时的版本,并且更新这个版本信息
==========================mysql=========================
事务隔离级别:https://www.cnblogs.com/ubuntu1/p/8999403.html
Mysql索引
B+数原理:https://www.bilibili.com/video/av79127293?p=11
什么是聚集索引:
索引是通过B+树的数据结构来描述的,我们可以这么理解聚簇索引:索引的叶节点就是数据节点(索引和数据聚集到一起)。而非聚簇索引的叶节点仍然是索引节点,只不过有一个指针指向对应的数据块。
Innodb表为什么必须有主键:
因为InnoDB的数据文件本身要按主键聚集,所以InnoDB要求表必须有主键(MyISAM可以没有),如果没有显式指定,则MySQL系统会自动选择一个可以唯一标识数据记录的列作为主键,如果不存在这种列,则MySQL自动为InnoDB表生成一个隐含字段作为主键,这个字段长度为6个字节,类型为长整形。
Innodb主键为什么尽量使用自增的:
分库分表
1、区间范围
2、区域
3、hash取模
跨库分页查询:(每页100条,按时间排序)
1、为了数据的精准性,只能每个库各取100条,然后合并内存中排序取出top100;
将order by time offset X limit Y,改写成order by time offset 0 limit X+Y
最致命的,这个算法随着页码的增大,性能会急剧下降,这是因为SQL改写后每个分库要返回X+Y行数据:
返回第3页,offset中的X=200;假如要返回第100页,offset中的X=9900,即每个分库要返回100页数据,数据量和排序量都将大增,性能平方级下降。
2、考虑业务折衷:只允许下一页,不能直接跳转到指定页,这样每次取都可以用上一页的最大时间作为条件再取页的数据。
name like %name 和 name like %name% 都会造成索引失效,全表扫描
解决方案:
name like name%这样可以避免
真的需要两边都使用%来模糊查询时,只有当这个作为模糊查询的条件字段(例子中的name)以及所想要查询出来的数据字段都在索引列上时,
才能真正使用索引,否则任意一个查询出来的字段不在索引列上时,都会索引失效全表扫描
覆盖索引:SQL只需要通过索引就可以返回查询所需要的数据,而不必通过二级索引查到主键之后再去查询数据。
https://blog.csdn.net/qq_28584889/article/details/88778741
=========================分布式事务======================
中间状态、补偿、最终一致性
分布式事务
两阶段提交,下订单预提交、扣库存预提交,通过zk协调器,两个都是success的话,协调器
通知两个数据源进行真正的commit
无法绝对满足acid,可以再通过事务补偿机制,记录操作log,通过统一的id找到一组操作
两阶段提交缺点,会锁表牺牲了可用性,如果微服务很多一次操作可能跨多个源肯定不可以接受
柔性事务:
cap理论:
atomikos
分布式唯一主键:雪花算法实现
=====================消息中间件=====================
解耦、异步、削峰
消息队列
kafaka:(一个分区只能被组里面的一个消费者消费)
1、重复消费
通过offset偏移指针(保存到zookepeer)标记消费到了哪里,可以消费多条一次提交,如果消费一批中某个异常挂掉了导致没有提交,次视没有记着偏移位,下次就可能导致重复消费问题。
解决重复消费保证幂等问题:
(1)比如你拿个数据要写库,你先根据主键查一下,如果这数据都有了,你就别插入了,update一下
(2)比如你是写redis,那没问题了,反正每次都是set,天然幂等性
https://blog.csdn.net/u013425438/article/details/102553536
2、消息丢失
(1)对于生产端丢消息:ack=all 保证消息所有节点都会同步到才算生产成功(保证可靠消息),不然master宕机还没有同步到其它broker。
一般比较重要的消息才会这么做,不然影响吞吐率。
(2)对于消费端丢消息:接收到消息直接入库,然后再去执行消费逻辑,并且采用定时补偿机制,防止消息失败
3、消息堆积
kafaka:(一个分区只能被组里面的一个消费者消费),如果ramitmq可以添加消费者
(1)多建几个分区,用原来的消费端把消息转发到扩容的分区,然后再用对应的消费端消费
(2)消费端收到先暂时不做任何操作直接返回,让kafaka清掉消息
4、消息顺序
Kafka官方保证了在一个partition内部的数据有序性(追加写、offset读);
为了提高Topic的并发吞吐能力,可以提高Topic的partition数,
并通过设置partition的replica来保证数据高可靠;但是在多个Partition时,
不能保证Topic级别的数据有序性。因此,如果你们就像死磕kafka,但是对数据有序性有严格要求,
那我建议:创建Topic只指定1个partition,这样的坏处就是磨灭了kafka最优秀的特性。
所以可以思考下是不是技术选型有问题, kafka本身适合与流式大数据量,要求高吞吐,
对数据有序性要求不严格的场景。
rocketmq:生产消息是一个队列和我们消费消息是一个队列
消息中间件确定:系统复杂度提高、数据一致性
**Broker:**Kafka 集群包含一个或多个服务器,这种服务器被称为 broker。
Topic:每条发布到 Kafka 集群的消息都有一个类别,这个类别被称为 Topic。(物理上不同 Topic 的消息分开存储,逻辑上一个 Topic 的消息虽然保存于一个或多个 broker 上,但用户只需指定消息的 Topic 即可生产或消费数据而不必关心数据存于何处)。
**Partition:**Partition 是物理上的概念,每个 Topic 包含一个或多个 Partition。为了实现扩展性,一个非常大的topic可以分布到多个broker(即服务器)上。kafka只保证按一个partition中的顺序将消息发给consumer,不保证一个topic的整体(多个partition间)的顺序。
Producer:负责发布消息到 Kafka broker。
Consumer:消息消费者,向 Kafka broker 读取消息的客户端。
Consumer Group:每个 Consumer 属于一个特定的 Consumer Group(可为每个 Consumer 指定 group name,若不指定 group name 则属于默认的 group)。这是kafka用来实现一个topic消息的广播(发给所有的consumer)和单播(发给任意一个consumer)的手段。一个 topic可以有多个CG。topic的消息会复制(不是真的复制,是概念上的)到所有的CG,但每个CG只会把消息发给该CG中的一个 consumer。如果需要实现广播,只要每个consumer有一个独立的CG就可以了。要实现单播只要所有的consumer在同一个CG。用CG还 可以将consumer进行自由的分组而不需要多次发送消息到不同的topic。
Kakfa提供了两种策略来删除数据。一是基于时间,二是基于partition文件大小。
Kafka为啥快?
每次读写都会寻址->写入,Kafka就是使用顺序I/O。
Kafka的数据并不是实时的写入硬盘,它充分利用了现代操作系统分页存储来利用内存提高I/O效率。
Memory Mapped Files(后面简称mmap)也被翻译成内存映射文件,在64位操作系统中一般可以表示20G的数据文件,它的工作原理是直接利用操作系统的Page来实现文件到物理内存的直接映射。完成映射之后你对物理内存的操作会被同步到硬盘上(操作系统在适当的时候)。
Kafka是用mmap作为文件读写方式的,它就是一个文件句柄,所以直接把它传给sendfile;偏移也好解决,用户会自己保持这个offset,每次请求都会发送这个offset。(还记得吗?放在zookeeper中的);数据量更容易解决了,如果消费者想要更快,就全部扔给消费者。如果这样做一般情况下消费者肯定直接就被压死了;所以Kafka提供了的两种方式——Push,我全部扔给你了,你死了不管我的事情;Pull,好吧你告诉我你需要多少个,我给你多少个。
=================zk=========================
leader:负责读和写、选举投票权
follower:负责读、选举投票权
observer:负责读
4种节点类型:持久(有序)的、临时(有序)
持久节点:客户端断开节点不会自动删除
临时节点:客户端断开节点会自动删除
支持动态扩容节点,支持不是很好(需要停机器,加配置才可以conf/zoo.cfg server1,server2 )
集群方式:单机、集群、伪集群(在一台上)
=======================ELK=====================
ES集群中的节点有三种不同的类型:
主节点:负责管理集群范围内的所有变更,例如增加、删除索引,或者增加、删除节点等。 主节点并不需要涉及到文档级别的变更和搜索等操作。可以通过属性node.master进行设置。
数据节点:存储数据和其对应的倒排索引。默认每一个节点都是数据节点(包括主节点),可以通过node.data属性进行设置。
协调节点:如果node.master和node.data属性均为false,则此节点称为协调节点,用来响应客户请求,均衡每个节点的负载。
https://blog.csdn.net/yydu_666/article/details/82782561
===================MongoDb===================
可以说MongoDB的副本集
是自带故障转移功能的主从复制。
相对于传统主从模式的优势
传统的主从模式,需要手工指定集群中的 Master。如果 Master 发生故障,一般都是人工介入,指定新的 Master。 这个过程对于应用一般不是透明的,往往伴随着应用重
新修改配置文件,重启应用服务器等。而 MongoDB 副本集,集群中的任何节点都可能成为 Master 节点。一旦 Master 节点故障,则会在其余节点中选举出一个新的 Master 节点。 并引导剩余节点连接到新的 Master 节点。这个过程对于应用是透明的。
https://www.cnblogs.com/nulige/p/7613721.html
为什么Mongodb索引用B树,而Mysql用B+树?