都是NoSQLs数据库:非关系型数据库。mysql就是关系型数据库。
redis | mongodb | memcache | |
---|---|---|---|
数据类型 | 五大类型 string、list、hash、sorted set 、set |
key-value 值可以是文档,数组及文档数组 |
key-value |
线程 | 单核单线程 | 多线程 | 多核多线程 |
主要存储形式 | 内存(也可持久化到磁盘) | 磁盘 | 内存 |
主从模式(分布) | 支持 | 支持 | 不支持 |
自动复制 | 支持 | 支持 | 不支持 |
TPS性能 | 高 | 稍弱 | 高 |
分片 | 支持 | 支持 | 支持 |
过期策略 | 支持 | 不支持 | 支持 |
自动故障恢复 | 哨兵模式 | 内部paxos选举 | 不支持 |
事务支持 | 支持(稍弱,事务中的每个操作连续执行 | 不支持 | 支持(cas保证) |
消息发布/订阅 | 支持 | 不支持 | 不支持 |
断电数据恢复 | 支持 | 支持 | 不支持 |
编写语言 | ANSI C | C++ | C |
应用场景 | 数据量较小但更性能操作和运算上 | 海量数据的访问效率问题 | 减少数据库负载,提升性能;做缓存,提高性能 |
(1)ActiveMQ支持多种消息协议,包括AMQP,MQTT,Stomp等,并且支持JMS规范,但Redis没有提供对这些协议的支持;
(2)ActiveMQ提供持久化功能,但Redis无法对消息持久化存储,一旦消息被发送,如果没有订阅者接收,那么消息就会丢失;
(3)ActiveMQ提供了消息传输保障,当客户端连接超时或事务回滚等情况发生时,消息会被重新发送给客户端,Redis没有提供消息传输保障。
(4) MQ 提供了丰富的发布订阅方式,例如 queue、topic。还有 ack 消息确认机制,以及推送和主动拉取消息的选择方式。
总之,ActiveMQ所提供的功能远比Redis发布订阅要复杂,毕竟Redis不是专门做发布订阅的。
1.执行 top 命令,查看占用cpu使用率最高的 pid 进程
2.使用 top -Hp pid ,键入大写P,按照cpu使用率排序,找出最耗cpu的线程id
3.将线程 id 转换成 16 进制(堆栈里面线程id 是16进制表示的)
4.使用 jstack pid | grep '线程id(16进制)' -C5 --color 查看最耗cpu的线程
5.找到对应代码进行排查。
使用top ,查看 %MEM% 比较高的 pid
jmap -heap pid 查看堆内存使用情况,
jmap -histo:live pid | head 打印出前几条占用情况
jmap -dump:live,format=b,file=myheap.dump pid 导出堆内存到文件
导出后,本地打开 Java visualvm,导入刚才导出的文件,可以查看到占用空间比较大的类以及详细
主要是减少FGC,尽量让对象在新生代被回收掉。FGC:会对整个堆进行整理,包括Young、Tenured和Perm。
导致Full GC的原因
1)年老代(Tenured)被写满
调优时尽量让对象在新生代GC时被回收、让对象在新生代多存活一段时间和不要创建过大的对象及数组避免直接在旧生代创建对象 。
2)持久代Pemanet Generation空间不足
增大Perm Gen空间,避免太多静态对象 , 控制好新生代和旧生代的比例
3)System.gc()被显示调用
垃圾回收不要手动触发,尽量依靠JVM自身的机制
https://www.cnblogs.com/Darrenblog/p/10712125.html
GC常见算法:
1.标记—清除算法
2.复制算法
3.标记—整理算法
4.分代收集算法
当前主流的JVM大都采用分代收集算法,也就是说根据不同的区域,使用不同的算法。例如:新生代,存活率比较低,可以采用复制算法;老年代,存活率很高,可以采用标记-清除或者标记-整理算法。
https://my.oschina.net/solidwang/blog/1589754
主键索引、唯一索引、全文索引、组合索引
(1)组合索引未使用最左前缀,例如组合索引(A,B),where B=b不会使用索引;
(2)like未使用最左前缀,where A like '%China';
(3)搜索一个索引而在另一个索引上做order by,where A=a order by B,只使用A上的索引,因为查询只使用一个索引 ;
(4)or会使索引失效。如果查询字段相同,也可以使用索引。例如where A=a1 or A=a2(生效),where A=a or B=b(失效)
(5)如果列类型是字符串,要使用引号。例如where A='China',否则索引失效(会进行类型转换);
(6)在索引列上的操作,函数(upper()等)、or、!=(<>)、not in等;
https://blog.csdn.net/qq_37050329/article/details/88777937
Spring 配置
Isolation.DEFAULT 默认,使用数据库默认的隔离级别
隔离级别越往下,安全性越高,数据越安全。
Isolation.READ_UNCOMMITTED 读未提交,即使没有提交,但是做了更改也可以被读到。会产生脏读、幻读,不可重复读。
Isolation.READ_COMMITTED 读已提交,只读取已经提交的事务。会产生幻读,不可重复读。
Isolation.REPEATABLE_READ 可重复读,两个事务之间的读写不冲突。当一个事务进行数据读取,另一个事务进行了修改之 后,第一个事务再次读取,但是数据依旧和第一次读到的一样。可重复读
Isolation.SERIALIZABLE 序列化。效率低。不会脏读、幻读、重复读
mysql默认的事务处理级别是'REPEATABLE-READ',也就是可重复读
oracle 默认系统事务隔离级别是READ COMMITTED,也就是读已提交
beanfactory 是个 factory ,也就是 IOC容器(spring 容器)或对象工厂。在spring中,所有的bean都由 beanfactory 来管理,提供了实例化对象和获取的功能。
使用场景:
FactoryBean 是个 bean,这个bean不是简单的bean,而是一个能生产或者修饰对象生成的工厂bean,它的实现与设计模式中的工厂模式和修饰器模式类似。
使用场景:
ProxyFactoryBean
在计算机科学中, CAP定理(CAP theorem), 又被称作 布鲁尔定理(Brewer's theorem), 它指出对于一个分布式计算系统来说,不可能同时满足以下三点:
一般只能满足两个
1、A (Atomicity) 原子性
2、C (Consistency) 一致性
3、I (Isolation) 独立性(隔离性)
4、D (Durability) 持久性
JAVA种的设计模式:23种设计模式
mybatis 的缓存
联表查询优化
Feign、hystrix、ribbon 调用关系
JDK动态代理只能对实现了接口的类生成代理,而不能针对类,它的实现原理是通过InvocationHandler.invoke方法实现对实现类方法的调用(InvocationHandler实例已经持有了对实现类对象的引用了),然后实现方法前后的拦截。
CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法(继承),然后通过MethodIntercept.intercept方法来实现在调用父类方法的前后执行拦截。
jdk代理是通过持有实现类的引用来实现对实现类方法的调用的,而CGLIB是通过调用父类的方法来实现对被代理类的方法调用的。
(1)当Bean实现接口时,Spring就会用JDK的动态代理。
(2)当Bean没有实现接口时,Spring使用CGlib实现。
(3)可以强制使用CGlib(在spring配置中加入
Class.forName("")
类.class
类.class.getClass()
(1)通过命令行启动应用时由JVM初始化加载含有main()方法的主类。
(2)通过Class.forName()方法动态加载,会默认执行初始化块(static{}),但是Class.forName(name,initialize,loader)中的initialze可指定是否要执行初始化块。
(3)通过ClassLoader.loadClass()方法动态加载,不会执行初始化块。
JMM(JAVA内存模型 java Memory Model)本身是一种抽象的概念并不真实存在,他描述的是一组规则或规范,通过这组规范定义了程序中各个变量(包括实例字段,静态字段和构成数组对象的元素)的访问方式。
JMM关于同步的规定:
1 线程解锁前,必须把共享变量的值刷新到主内存
2 线程加锁前,必须读取主内存的最新值到自己的工作内存
3 加锁解锁是同一把锁
JMM坚持三原则
1.可见性 通过volatile 关键字解决
2.原子性 通过 Atomic 类来解决
3.有序性 通过volatile 关键字解决
众所周知,程序运行时的所有变量都是存在内存中的。线程运行时,会从内存中copy一份到自己的工作内存空间去。加锁前需要获取最新的数据,解锁前需要同步到内存中,防止其它线程使用时不是最新的。
JMM
Lambda 表达式 − Lambda 允许把函数作为一个方法的参数(函数作为参数传递到方法中)。
方法引用 − 方法引用提供了非常有用的语法,可以直接引用已有Java类或对象(实例)的方法或构造器。与lambda联合使用,方法引用可以使语言的构造更紧凑简洁,减少冗余代码。
默认方法 − 默认方法就是一个在接口里面有了一个实现的方法。
新工具 − 新的编译工具,如:Nashorn引擎 jjs、 类依赖分析器jdeps。
Stream API −新添加的Stream API(java.util.stream) 把真正的函数式编程风格引入到Java中。
Date Time API − 加强对日期与时间的处理。
Optional 类 − Optional 类已经成为 Java 8 类库的一部分,用来解决空指针异常。
Nashorn, JavaScript 引擎 − Java 8提供了一个新的Nashorn javascript引擎,它允许我们在JVM上运行特定的javascript应用。
Java 8 新特性
BIO:阻塞IO。即每个连接都需要开启一个线程去处理
NIO:Linux 中非阻塞IO (NON-BLOCKING IO),交由select 轮询文件描述符即可。 java 中为 new IO。
同步阻塞:NIO。程序自己读取,调用了方法一直等到有返回为止。
同步非阻塞:程序自己读取,调用方法的一瞬间,给出是否读到(下一次读取时间程序自己控制)。
异步有没有阻塞?没有,没有意义,只有异步非阻塞。
不管NIO、SELECT、POLL都是要遍历所有的fd IO。差异:NIO时代,需要程序自己遍历,用户态和内核态不断切换。SELECT、POLL时代(多路复用),这些遍历经过了一次系统调用,由程序将文件描述符交给内核遍历。
多路复用缺点:1.每次都需要重新传入fds 2.每次内核被调用后,都会触发一个遍历fds全量的复杂度
javac 生成class 文件,class 文件加载(涉及到 class 加载步骤、class loader知识、Java 内存结构),垃圾回收。
垃圾回收
程序计数器(PC 寄存器):存放下一条指令位置
jvm栈:每个线程对应一个栈,每个方法对应一个栈帧。
栈帧:动态链接、局部变量表、操作数栈、方法返回地址。动态链接:动态链接是一个将符号引用解析为直接引用的过程 动态链接解释
native 方法栈:本地方法栈
heap 堆:所有的对象实例以及数组都要在堆上分配。回收器主要管理的对象。摘自
metaspace 元数据区:存储类信息、常量、静态变量、即时编译器编译后的代码。
每个线程都有自己的独享的 程序计数器、虚拟机方法栈、native 方法栈 空间,共享堆和方法区内存。
jvm原理参考
MQ原理:
几个概念说明:
Broker:它提供一种传输服务,它的角色就是维护一条从生产者到消费者的路线,保证数据能按照指定的方式进行传输,
Exchange:消息交换机,它指定消息按什么规则,路由到哪个队列。
Queue:消息的载体,每个消息都会被投到一个或多个队列。
Binding:绑定,它的作用就是把exchange和queue按照路由规则绑定起来.
Routing Key:路由关键字,exchange根据这个关键字进行消息投递。
vhost:虚拟主机,一个broker里可以有多个vhost,用作不同用户的权限分离。
Producer:消息生产者,就是投递消息的程序.
Consumer:消息消费者,就是接受消息的程序.
Channel:消息通道,在客户端的每个连接里,可建立多个channel.
Pub/Sub发布订阅
希望发送的消息可以不被做任何处理、或者只被一个消息者处理、或者可以被多个消费者处理的话,那么可以采用Pub/Sub模型
PTP点对点
如果希望发送的每个消息都会被成功处理的话,那么需要P2P模式。
多点广播
MQ适用于不同类型的应用。其中重要的,也是正在发展中的是"多点广播"应用,即能够将消息发送到多个目标站点(Destination List)。可以使用一条MQ指令将单一消息发送到多个目标站点,并确保为每一站点可靠地提供信息。MQ不仅提供了多点广播的功能,而且还拥有智能消息分发功能,在将一条消息发送到同一系统上的多个用户时,MQ将消息的一个复制版本和该系统上接收者的名单发送到目标MQ系统。目标MQ系统在本地复制这些消息,并将它们发送到名单上的队列,从而尽可能减少网络的传输量
群集(Cluster)
为了简化点对点通讯模式中的系统配置,MQ提供Cluster(群集)的解决方案。群集类似于一个域(Domain),群集内部的队列管理器之间通讯时,不需要两两之间建立消息通道,而是采用群集(Cluster)通道与其它成员通讯,从而大大简化了系统配置。此外,群集中的队列管理器之间能够自动进行负载均衡,当某一队列管理器出现故障时,其它队列管理器可以接管它的工作,从而大大提高系统的高可靠性
Zookeeper的核心是原子广播,这个机制保证了各个Server之间的同步。实现这个机制的协议叫做Zab协议。Zab协议有两种模式,它们分 别是恢复模式(选主)和广播模式(同步)。当服务启动或者在领导者崩溃后,Zab就进入了恢复模式,当领导者被选举出来,且大多数Server完成了和 leader的状态同步以后,恢复模式就结束了。状态同步保证了leader和Server具有相同的系统状态。
ZAB协议
为了保证事务的顺序一致性,zookeeper采用了递增的事务id号(zxid)来标识事务。所有的提议(proposal)都在被提出的时候加上 了zxid。实现中zxid是一个64位的数字,它高32位是epoch用来标识leader关系是否改变,每次一个leader被选出来,它都会有一个 新的epoch,标识当前属于那个leader的统治时期。低32位用于递增计数。
rpc,远程服务调用。调用远程服务像调用本地方法一样。
长链接,不必每次通信都要像http一样去3次握手什么的,减少了网络开销;其次就是RPC框架一般都有注册中心,有丰富的监控管理;发布、下线接口、动态扩展等,对调用方来说是无感知、统一化的操作。
Java容器
queue和List的区别
Queue 和 List 的区别,Queue 添加了很多对线程友好的API: offer、peek、poll
peek 返回队首的元素
poll: 返回队首并移除元素
offer: 插入元素到队尾,如果满了也不阻塞
LindedBlockingQueue : put、take. 线程阻塞.
LVS & nginx
nginx工作在七层(反向代理),可以实现比较灵活的负载均衡策略。
lvs工作在四层,基本上是不能根据请求报文做负载均衡的,纯粹是均衡流量,数据包返回可以不经过lvs。只做请求转发。
快速运算符
5 << 1 = 5 * 2
5 >> 1 = 5 / 2
(5 << 1) | 1= 5 * 2 + 1
(5 << 1) & 1= 5 * 2 - 1