面试常问题汇总、redis 、 mangodb 、 memcache对比

 redis 、 mangodb 、 memcache

都是NoSQLs数据库:非关系型数据库。mysql就是关系型数据库。

  redis mongodb memcache
数据类型

五大类型

string、list、hash、sorted set 、set

key-value

值可以是文档,数组及文档数组

key-value
线程 单核单线程 多线程

多核多线程

主要存储形式 内存(也可持久化到磁盘) 磁盘 内存
主从模式(分布) 支持 支持 不支持
自动复制 支持 支持 不支持
TPS性能 稍弱
分片 支持 支持 支持
过期策略 支持 不支持 支持
自动故障恢复 哨兵模式 内部paxos选举 不支持
事务支持 支持(稍弱,事务中的每个操作连续执行 不支持 支持(cas保证)
消息发布/订阅 支持 不支持 不支持
断电数据恢复 支持 支持 不支持
编写语言 ANSI C C++ C
应用场景 数据量较小但更性能操作和运算上 海量数据的访问效率问题 减少数据库负载,提升性能;做缓存,提高性能

 

Redis发布订阅与ActiveMQ的比较

(1)ActiveMQ支持多种消息协议,包括AMQP,MQTT,Stomp等,并且支持JMS规范,但Redis没有提供对这些协议的支持; 
(2)ActiveMQ提供持久化功能,但Redis无法对消息持久化存储,一旦消息被发送,如果没有订阅者接收,那么消息就会丢失; 
(3)ActiveMQ提供了消息传输保障,当客户端连接超时或事务回滚等情况发生时,消息会被重新发送给客户端,Redis没有提供消息传输保障。 

  (4) MQ 提供了丰富的发布订阅方式,例如 queue、topic。还有 ack 消息确认机制,以及推送和主动拉取消息的选择方式。
总之,ActiveMQ所提供的功能远比Redis发布订阅要复杂,毕竟Redis不是专门做发布订阅的。
 

JVM调优

cpu 100%

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,导入刚才导出的文件,可以查看到占用空间比较大的类以及详细

 

jvm优化:

主要是减少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

 

Mysql

常见的索引:

主键索引、唯一索引、全文索引、组合索引

索引何时失效


    (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等;

联表查询:

  1. 尽量使用内联查询,回会子查询快
  2. 尽量使用索引查询
  3. 需要order by的字段尽量是索引字段
  4. 尽量不要对索引字段使用函数
  5. 使用小表转大表。即A表数据量大,B表少,则使用 A right join B,或者 B left join A。默认情况下join_buffer_size=256K,在查找的时候MySQL会将所有的需要的列缓存到join buffer当中。使用where 并使用到index字段(尽量让执行的sql使用 Index Nested-Loop Join、Block Nested-Loop Join)。
  6. where条件中的字段尽量是一张表中的,且有索引字段,外联时优先外联这张表。

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,也就是读已提交

面试常问题汇总、redis 、 mangodb 、 memcache对比_第1张图片

事务的隔离级别(spring)

  1. Propagation.REQUIRED  如果有事务在运行,当前的这个方法就在事务内运行.否则就开启新的事务,在自己的事务内运行
  2. Propagation.REQUIRES_NEW    当前的方法必须启动新事务,并在自己的事务内运行。如果有事务在运行,将它挂起
  3. Propagation.MANDATORY    当前的方法必须运行在事务内部,如果没有正在运行的事务则抛出异常
  4. Propagation.NEVER   当前的方法不应该运行在事务内,如果有运行的事务,就抛出异常
  5. Propagation.NESTED   如果有事务在运行,当前的方法就应该在这个事务的嵌套事务内运行。否则就启动一个新的事务,在自己的事务内运行。
  6. Propagation.SUPPORTS  如果有事务在运行,当前的方法就在这个事务内运行.否则它可以不运行在事务中
  7. Propagation.NOT_SUPPORTED   当前的事务不应该运行在事务中,如果有运行的事务,就将它挂起 

 

BeanFactory 和 FactoryBean的区别

beanfactory 是个 factory ,也就是 IOC容器(spring 容器)或对象工厂。在spring中,所有的bean都由 beanfactory 来管理,提供了实例化对象和获取的功能。

使用场景:

  • 从 IOC 容器中获取bean
  • 检索 IOC 容器是否包含指定的bean
  • 判断bean是否是单例

FactoryBean 是个 bean,这个bean不是简单的bean,而是一个能生产或者修饰对象生成的工厂bean,它的实现与设计模式中的工厂模式和修饰器模式类似。

使用场景:

ProxyFactoryBean

 

spring bean的生命周期

  1. 实例化 Instantiation
  2. 属性赋值 Populate
  3. 初始化 Initialization
  4. 销毁 Destruction

spring IOC容器初始化过程

  1. resource 资源定位
  2. BeanDefinition 载入,把用户定义好的bean 表示成IOC容器内部的数据结构
  3. 向IOC容器注册这些 BeanDefinition 的过程,保存到 hashmap


名词

CAP定理(CAP theorem)

在计算机科学中, CAP定理(CAP theorem), 又被称作 布鲁尔定理(Brewer's theorem), 它指出对于一个分布式计算系统来说,不可能同时满足以下三点:

  • 一致性(Consistency) (所有节点在同一时间具有相同的数据)
  • 可用性(Availability) (保证每个请求不管成功或者失败都有响应)
  • 分隔容忍(Partition tolerance) (系统中任意信息的丢失或失败不会影响系统的继续运作)

一般只能满足两个

  • CA - 单点集群,满足一致性,可用性的系统,通常在可扩展性上不太强大。
  • CP - 满足一致性,分区容忍必的系统,通常性能不是特别高。
  • AP - 满足可用性,分区容忍性的系统,通常可能对一致性要求低一些。

ACID

1、A (Atomicity) 原子性

2、C (Consistency) 一致性

3、I (Isolation) 独立性(隔离性)

4、D (Durability) 持久性

 

JAVA种的设计模式:23种设计模式

 

mybatis 的缓存

联表查询优化

 

 

Feign、hystrix、ribbon 调用关系

面试常问题汇总、redis 、 mangodb 、 memcache对比_第2张图片

 

jdk代理和CGLIB代理的区别
一、简单来说:

JDK动态代理只能对实现了接口的类生成代理,而不能针对类,它的实现原理是通过InvocationHandler.invoke方法实现对实现类方法的调用(InvocationHandler实例已经持有了对实现类对象的引用了),然后实现方法前后的拦截。

CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法(继承),然后通过MethodIntercept.intercept方法来实现在调用父类方法的前后执行拦截。
  
  jdk代理是通过持有实现类的引用来实现对实现类方法的调用的,而CGLIB是通过调用父类的方法来实现对被代理类的方法调用的。

 

二、Spring在选择用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内存模型

JMM(JAVA内存模型 java Memory Model)本身是一种抽象的概念并不真实存在,他描述的是一组规则或规范,通过这组规范定义了程序中各个变量(包括实例字段,静态字段和构成数组对象的元素)的访问方式。

JMM关于同步的规定:

1 线程解锁前,必须把共享变量的值刷新到主内存

2 线程加锁前,必须读取主内存的最新值到自己的工作内存

3 加锁解锁是同一把锁

JMM坚持三原则

1.可见性 通过volatile 关键字解决

2.原子性 通过 Atomic 类来解决

3.有序性 通过volatile 关键字解决

众所周知,程序运行时的所有变量都是存在内存中的。线程运行时,会从内存中copy一份到自己的工作内存空间去。加锁前需要获取最新的数据,解锁前需要同步到内存中,防止其它线程使用时不是最新的。

JMM

 

了解Java 8吗?

  • 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、NIO

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全量的复杂度

面试常问题汇总、redis 、 mangodb 、 memcache对比_第3张图片

 

JVM原理

javac 生成class 文件,class 文件加载(涉及到 class 加载步骤、class loader知识、Java 内存结构),垃圾回收。

垃圾回收

Java 内存结构:

程序计数器(PC 寄存器):存放下一条指令位置

jvm栈:每个线程对应一个栈,每个方法对应一个栈帧。

栈帧:动态链接、局部变量表、操作数栈、方法返回地址。动态链接:动态链接是一个将符号引用解析为直接引用的过程  动态链接解释

native 方法栈:本地方法栈

heap 堆:所有的对象实例以及数组都要在堆上分配。回收器主要管理的对象。摘自

metaspace 元数据区:存储类信息、常量、静态变量、即时编译器编译后的代码。

 

面试常问题汇总、redis 、 mangodb 、 memcache对比_第4张图片

每个线程都有自己的独享的 程序计数器、虚拟机方法栈、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原理

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?

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

你可能感兴趣的:(redis,redis分布式缓存)