java面试题

173 阅读27分钟

关于面试的那点事

\

最近去面了挺多公司了

\

楼主是java后端三年工作经验,去面试的职位是高级java工程师,闲话不多说,直接上面试的一些大纲。

博客主要的讲解了一下大纲,具体的细节大家可以访问下面网址去下载对应的详细介绍。

download.csdn.net/detail/tian…\

链接地址是csdn下载资源,包含了详细的面试题目和一些学习知识点,已经被1000多人下载。

下面是百度网盘地址:新加了很多面试内容

pan.baidu.com/s/1c2jDGPE\

\

由于最近比较忙,所以博客写的比较简单,更多内容详见百度网盘下载地址和csdn资源下载地址,绝对良心分享

首先是java基础

1、StringUtils里面的isEmpty和isBlank的区别,主要在于对于空格的判断。

2.Switch能否用string做参数?string类型支持的原理?

在 Java 7之前,switch 只能支持 byte、short、char、int或者其对应的封装类以及 Enum 类型。在 Java 7中,String支持被加上了。

Switch对于String类型的支持原理是把string转为hashcode去做的路由,当hashcode相同时在使用equals方法去区分路由。

3、Collection包结构,与Collections的区别。

4、 try catch finally,try里有return,finally还执行么?

(1)、不管有木有出现异常,finally块中代码都会执行;

(2)、当try和catch中有return时,finally仍然会执行;

(3)、在try语句中,try要把返回的结果放置到不同的局部变量当中,执行finaly之后,从中取出返回结果,因此,即使finaly中对变量进行了改变,但是不会影响返回结果,因为使用栈保存返回值,即使在finaly当中进行数值操作,但是影响不到之前保存下来的具体的值,所以return影响不了基本类型的值,这里使用的栈保存返回值。而如果修改list,map,自定义类等引用类型时,在进入了finaly之前保存了引用的地址, 所以在finaly中引用地址指向的内容改变了,影响了返回值。

总结:

    1.影响返回结果的前提是在非 finally 语句块中有 return 且非基本类型

    2.不影响返回结果的前提是 非 finally 块中有return 且为基本类型

究其本质 基本类型在栈中存储,返回的是真实的值,而引用类型返回的是其浅拷贝堆地址.所以才会改变。

    return的若是对象,则先把对象的副本保存起来,也就是说保存的是指向对象的地址。若对原来的对象进行修改。对象的地址仍然不变,return的副本仍然是指向这个对象,所用finally中对对象的修改仍然有作用。而基本数据类型保存的是原原本本的数据,return保存副本后,在finally中修改都是修改原来的数据。副本中的数据还是不变,所以finally中修改对return无影响。

(4)、finally中最好不要包含return,否则程序会提前退出,返回值不是try或catch中保存的返回值。

5、HashMap和ConcurrentHashMap的区别,HashMap的底层源码,实现原理(数组加链表)。

jdk 1.7和1.8中hashmap的区别?jak7中hashmap是数组加链表实现的,jdk8中当链表的数据超过8个的时候就会转化为红黑树(时间复杂度为O(logn))。

今天被问了一个很高深的问题,使用hashmap的时候,一个线程通过迭代器去遍历hashmap,另外一个线程去修改数据,这时候遍历hashmap的线程会怎么样?能否继续遍历,能否遍历到新插入的数据?如果修改hashmap的线程是插入数据,插入数据导致hashmap需要去扩容,这种情况下遍历hashmap的线程有会怎么样了?

答案下期分享,先把问题记录下来。

6、ThreadPool原理、用法与优势。多线程题必问,主要问题几种创建方式,线程数量的配置,CPU密集型和IO密集型的区别怎么去配置。

5种threadPool的创建,构造函数的参数,怎么搭配对应的线程队列,抛弃策略等。

对于IO密集型配置线程数量为2倍的主机CPU,对于CPU密集型的配置为CPU数量-1。

7、volatile关键字的用法和需要注意的地方

主要就是线程间可见,就是一个线程修改了一个volatile关键字的变量,另一个线程可以看见,没有在临时缓存里面,直接修改堆里面的值

8、线程安全的集合有哪些,怎么实现的线程安全。

比较特殊的就是concurrent包下面的那些,concurrentHashMap,concurrentLinkedQueue等主要是要知道实现的原理,通过什么方式实现的线程安全,有什么优缺点。

9、java中的常用23种设计模式

设计模式问的很多,至少需要会写线程安全的单列。代理模式和装饰者模式的区别,代理模式是去修改被代理者的行为(比如权限控制),装饰者是增强被装饰者的功能。

10,java的继承,多态,和封装,一定要清楚。

一般就是两个类,父累和子类代码基本一样,一个构造方法,一个代码块,一个静态代码块,问具体的执行顺序。

优先执行父类的静态代码块,然后是子类的静态代码块,然后是父类的代码块,然后是父类的构造方法,然后是子类的代码块,然后是子类的构造方法。

11、CAS算法实现原理

使用JNI去实现原子操作,来实现线程安全,速度快,减少资源消耗。ABA问题的解决,加上时间错作为版本号,来解决ABA问题;自旋问题,如果主机支持pause指令,可以优化自旋的一个资源竞争。

\

============================================================================================================

二、java进阶篇

\

1、jvm原理,jvm虚拟机这本书一定要看一遍。或者去看jvm内存模型,jvm调优,linux下面怎么查看gc状态。full gc的触发条件,怎么解决full gc频繁的问题。

各种gc算法,gc收集器。主要看G1收集器,有点,区别。

对象的可达算法,标记可达对象为存活对象,不可达的为垃圾,对应的根都有哪些,根主要是方法栈里面的对象引用和静态方变量区的引用。

jvm调优经验,主要就是主机出现jvm内存泄漏问题的时候,首先使用top指令看一下是哪一个进程出现了问题,找到对应的进程ID,然后使用jstat命令查看一下gc的状态,看看是不是由于频繁的FullGc导致的,如果是,那么使用jmap -histo 命令查看一下是什么对象太大导致的内存问题,然后去jmap看一下堆栈信息,去代码里面查看具体的代码,解决问题。

\

jvm内存溢出的情况有哪些,主要是静态的集合里面死循环往里面不断添加创建的对象,很容易就导致堆溢出,递归调用没有正确的返回会导致栈溢出。

\

熟悉一下jvm的配置参数   -Xmx3550m最大堆内存 -Xms3550m初始大小 -Xmn2g年轻代大小   -Xss128k每一个线程栈大小

JVM使用并行收集器的时候默认使用 AdaptiveSizePolicy 策略自动分配Eden和Survivor空间大小。

所以设置XX:SurvivorRatio参数默认无效:

-XX:SurvivorRatio=8

使用以下参数,关闭AdaptiveSizePolicy,即可使Ratio生效:

-XX:-UseAdaptiveSizePolicy

有的可能会问jvm加载class的机制,看情况了解一下,属于jvm虚拟机的第三部分,比较高深。

\

---------------------------------------------------------------------------------------------------------------------------------------------------------------------

2、算法篇,算法是必看内容。主要围绕算法导论这本书,可以把简单的算法都看一下,包括简单的排序算法,插入,选择,快速排序,二分查找。 最优算法,贪心算法看情况看一下。平衡二叉树的各种遍历,主要看非递归遍历。

二分查找,二叉树的遍历,二维表格的最短路径问题等等

1、使用数组实现一个队列,简单的实现方法会导致删除数组第一个下标的值后,后面的值需要顺序往前移动一个位置,效率很慢,需要优化这个操作。添加一个队列头部和尾部的下标,然后实现操作下标的加减实现队列操作。

2、十进制转为二进制的算法,就是除二求余,余数就是二进制从右到左的二进制值,直到余数为0为止。

3、二维表格n列,m行,其中随机的分布着一些值为0的点,比如a[2][3] = 0; a[5][1] = 0;求不为0的元素到靠近它最近的那个0的元素的最短距离,横着和竖着的一格都表示路径长度为1,不能斜着走,只能横竖走。填充所有不为0的节点的值。比如a[0][0] = 7; a[4][0] =2; a[5][0] = 1;

4、一个链表,出现了异常情况,可能某个点出现了闭环,就是链表出现了环形,请找到出现环形的点并返回

5、有一个字典数组,是一个字符串数组,里面的值是“abc”、“bed”、“rf”、“ee”等字符串,现在我有一个字符串,字符串是一个变量,例如:“adcdef”,请写一个方法返回这个字符串能否由字典数组里面的字符串组成,只需要返回true或者false。

--------------------------------------------------------------------------------------------------------------------------------------------------------------------

3、mysql篇,主要看mysql的主要几种引擎,innoDB是核心,一定要知道它的索引类型,索引结构。B+树的优缺点,为什么选择B+树作为mysql的索引,主要是 IO读取快。联合索引abc,如果where条件使用 b ="xxx", c= "xxx"能使用索引吗?为什么?主要考最左匹配问题。 数据库分库分表问题,分表怎么多张表联合查询,主要考union的使用,和union all 的区别。 然后就是mysql最重要的优化了,explain查看sql执行情况必问,减少IO交互,建立查询索引等

左关联和左外关联的区别,外链接会对左边存在数据右边不存在的数据的情况下写上null填充。

使用group by 的时候需要注意除了分组的字段和需要计算的字段之外,其他字段显示的不正常,所以通过group by 最多只能查询出计算字段加分组字段,如果还需要展示其他字段需要在做一次关联查询才对。

数据库的事物

**事务ACID:   原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。
**

事物的级别,主要是未提交读(存在脏读问题),提交读(解决了脏读问题),可重复读(解决了幻读问题),可串行化。

脏读和幻读的区别,脏读主要是读取到了另外一个事物未提交的数据,然后另外一个事物回滚了。幻读是值同一个事物首先读取一个结果集,然后另外一个事务在这个结果集中添加了数据,第一个事务第二次读的时候发现和第一次读取的数据不一致,以为自己出现了幻觉。

\

select for update,行锁的使用

在SELECT 的读取锁定主要分为两种方式:

  SELECT ... LOCK IN SHARE MODE 

  SELECT ... FOR UPDATE

  这两种方式在事务(Transaction) 进行当中SELECT 到同一个数据表时,都必须等待其它事务数据被提交(Commit)后才会执行。

  而主要的不同在于LOCK IN SHARE MODE 在有一方事务要Update 同一个表单时很容易造成死锁。

  简单的说,如果SELECT 后面若要UPDATE 同一个表单,最好使用SELECT ... UPDATE。

\

\

然后就是数据库优化了

1、为你的主要查询建立索引,建立索引的好坏,怎么样的索引才是好的索引。

2、为你的查询开启查询缓存,mysql是有查询缓存的,通过修改my.cnf文件添加  query_cache_size = 20M   query_cache_type = ON。查看查询缓存状态使用 show variables like '%query_cache%'; 

3、使用EXPLAIN关键字优化你的查询比较慢的查询语句。

4、避免使用select *from 去查询数据,最好只返回你需要使用的字段,减少数据传输。

5、减少数据库IO是最能直接体现性能提升的,可以使用redis等查询缓存把热度比较高的数据放入缓存里面去。

6、使用分布式数据库,实现读写分离。写的情况也可以通过业务逻辑把相同的数据操作放到同一个数据库,不同的数据操作在不同数据库,保证数据的一致性和线程安全性,实现分布式写,能够大大提高高并发下的性能提升。

7、为每一个表设置一个数字的主键,千万不要使用varchar类型作为主键,会降低性能。

\

---------------------------------------------------------------------------------------------------------------------------------------------------

4、项目篇: 主要先让你讲一下项目的大概情况,然后就问你项目中你觉得是亮点的地方,一定要提前准备一些亮点重点介绍,很加分。 主要考点:

1、app节点宕机的时候缓存里面的数据怎么保证不会丢失,可以考虑使用消息队列

2、高并发访问的时候怎么去做一个限流,使用队列和IP限制等

3、多节点任务执行,节点之间数据交互,任务不会重复执行等。

4、模块之间实现解耦,怎么去解耦。

5、技术选型,项目为什么要选择这个架构,做一下竞品分析。主要就是讲和其他架构的区别,这个架构的优缺点等。

思考题:秒抢活动的设计,从架构设计方面去考虑,第一点是限流,第二点是保证不超卖,第三点是订单取消的数据回滚等等。

6、如果大家懂linux的话会有一定的加分,主要是基本的linux命令,shell脚本的编写等。

一般就会问问查看端口占用的命令 netstat -apn | grep 端口号;或者查看磁盘使用情况df -hl 可以查看磁盘使用情况。top命令查看cpu和内存的使用情况,lscpu查看cpu的详细信息;查看线程ps -ef ps -aux等等

shell编程的话一般会问#! /bin/sh的作用:指定执行sh文件的解释器存在的路径,不加这个能够执行sh文件吗:可以,会找到默认的解释器。 由于不同系统默认shell执行器不同,因此很容易出错,所以写shell脚本最好做声明。

shell脚本实现读取一个文件指定的5000-6000行的数据,使用sed -n 5000,6000

shell脚本实现读取一个文件的前几行使用head -n 10 读取前10行

more 和less的区别,more是查看文件使用分页的方式查询, less 工具也是对文件或其它输出进行分页显示的工具,应该说是linux正统查看文件内容的工具,功能极其强大。less 的用法比起 more 更加的有弹性。 在 more 的时候,我们并没有办法向前面翻, 只能往后面看,但若使用了 less 时,就可以使用 [pageup] [pagedown] 等按 键的功能来往前往后翻看文件,更容易用来查看一个文件的内容!除此之外,在 less 里头可以拥有更多的搜索功能,不止可以向下搜,也可以向上搜。

推荐看看鸟哥的私房菜,shell脚本编程等

\

\

========================================================================================================

三、框架篇

1、springMVC篇

IOC :其实这个 Spring 架构 核心的概念没有这么复杂,更不像有些书上描述的那样晦涩。 Java 程序员都知道: java 程序中的每个业务逻辑至少需要两个或以上的对象来协作完成,通常,每个对象在使用他的合作对象时,自己均要使用像 new object () 这样的语法来完成合作对象的申请工作。你会发现:对象间的耦合度高了。而 IOC 的思想是: Spring 容器来实现这些相互依赖对象的创建、协调工作。对象只需要关系业务逻辑本身就可以了。从这方面来说,对象如何得到他的协作对象的责任被反转了( IOC )。
总结:控制的什么被反转了?就是:获得依赖对象的方式反转了。

\

springmvc为什么要引入IOC了?因为实现了对象依赖关系的解耦和自动管理对象的生命周期

AOP 面向切面编程,使用动态代理模式实现的。

为什么要使用代理,当 需求发生了变化,要求项目中所有的类在执行方法时输出执行耗时。最直接的办法是修改源代码

但是缺点如下:

1、工作量特别大,如果项目中有多个类,多个方法,则要修改多次。

2、违背了设计原则:开闭原则(OCP),对扩展开放,对修改关闭,而为了增加功能把每个方法都修改了,也不便于维护。

3、违背了设计原则:单一职责(SRP),每个方法除了要完成自己本身的功能,还要计算耗时、延时;每一个方法引起它变化的原因就有多种。

4、违背了设计原则:依赖倒转(DIP),抽象不应该依赖细节,两者都应该依赖抽象。\

AOP(Aspect-Oriented Programming,面向切面编程)

切面(Aepect):横切关注点(跨越应用程序多个模块的功能)被模块化的对象;

通知(Advice):切面必须要完成的工作;

目标(Target):被通知的对象;

代理(Proxy):像目标对象应用通知之后创建的对象;

连接点(Joinpoint):程序执行的某个特殊位置,如类某个方法调用前、调用后、方法抛出异常后等。连接点由两个信息确定:方法表示的程序执行点;想对点表示的方位。

切点(pointcut):每个类都拥有多个连接点,即连接点是程序类中客观存在的事务;  

AOP通过切点定位到特定的连接点。

AOP的主要编程对象是切面(aopect),而切面模块化横切关注点。

在应用AOP编程时,仍需要定义公共功能,但可以明确这个功能在哪里,以什么方式应用,并且不必修改受影响的类,这样的话横切关注点就被模块化到特殊的对象(切面)里。

AOP的好处:

  每个事物逻辑位于一个位置,代码不分散,便于维护和升级;

  业务模块更简洁,值包含核心业务代码

Spring框架里的bean,或者说组件,获取实例的时候都是默认的单例模式,这是在多线程开发的时候要尤其注意的地方。

Spring 使用 ThreadLocal 解决线程安全问题  ,或者当我们需要修改service累或者javabean里面的成员变量的时候需要主动加锁去实现修改。\

\

SPRING 的事物传播级别

在service类前加上@Transactional,声明这个service所有方法需要事务管理。每一个业务方法开始时都会打开一个事务。

Spring默认情况下会对运行期例外(RunTimeException)进行事务回滚。这个例外是unchecked

如果遇到checked意外就不回滚。

如何改变默认规则:

1 让checked例外也回滚:在整个方法前加上 @Transactional(rollbackFor=Exception.class)

2 让unchecked例外不回滚: @Transactional(notRollbackFor=RunTimeException.class)

3 不需要事务管理的(只查询的)方法:@Transactional(propagation=Propagation.NOT_SUPPORTED)

在整个方法运行前就不会开启事务

       还可以加上:@Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true),这样就做成一个只读事务,可以提高效率。

       各种属性的意义:

       REQUIRED:业务方法需要在一个容器里运行。如果方法运行时,已经处在一个事务中,那么加入到这个事务,否则自己新建一个新的事务。

       NOT_SUPPORTED:声明方法不需要事务。如果方法没有关联到一个事务,容器不会为他开启事务,如果方法在一个事务中被调用,该事务会被挂起,调用结束后,原先的事务会恢复执行。

       REQUIRESNEW:不管是否存在事务,该方法总汇为自己发起一个新的事务。如果方法已经运行在一个事务中,则原有事务挂起,新的事务被创建。

       MANDATORY:该方法只能在一个已经存在的事务中执行,业务方法不能发起自己的事务。如果在没有事务的环境下被调用,容器抛出例外。

       SUPPORTS:该方法在某个事务范围内被调用,则方法成为该事务的一部分。如果方法在该事务范围外被调用,该方法就在没有事务的环境下执行。

       NEVER:该方法绝对不能在事务范围内执行。如果在就抛例外。只有该方法没有关联到任何事务,才正常执行。

       NESTED:如果一个活动的事务存在,则运行在一个嵌套的事务中。如果没有活动事务,则按REQUIRED属性执行。它使用了一个单独的事务,这个事务拥有多个可以回滚的保存点。内部事务的回滚不会对外部事务造成影响。它只对DataSourceTransactionManager事务管理器起效。


**
**

-----------------------------------------------------------------------------------------------------------------------------------------------

2、mybatis篇

\

有关mybatis的原理详解可以参考一下另外一篇博客,讲的很好

地址为:blog.csdn.net/luanlouis/a…

MyBatis的缓存
MyBatis的缓存分为一级缓存和二级缓存,
一级缓存放在session里面,默认就有,二级缓存放在它的命名空间里,默认是打开的,
使用二级缓存属性类需要实现Serializable序列化接口(可用来保存对象的状态),可在它的映射文件中配置<cache/>\

1、#{}和${}的区别是什么?

答:${}是Properties文件中的变量占位符,它可以用于标签属性值和sql内部,属于静态文本替换,比如${driver}会被静态替换为com.mysql.jdbc.Driver。#{}是sql的参数占位符,Mybatis会将sql中的#{}替换为?号,在sql执行前会使用PreparedStatement的参数设置方法,按序给sql的?号占位符设置参数值,比如ps.setInt(0, parameterValue),#{item.name}的取值方式为使用反射从参数对象中获取item对象的name属性值,相当于param.getItem().getName()。

2、Mybatis是如何进行分页的?分页插件的原理是什么?

答:Mybatis使用RowBounds对象进行分页,它是针对ResultSet结果集执行的内存分页,而非物理分页,可以在sql内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。

分页插件的基本原理是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数。

举例:select * from student,拦截sql后重写为:select t.* from (select * from student)t limit 0,10

3、怎么防止sql注入

\

\

\

-------------------------------------------------------------------------------------------------------------------------

3、redis篇

Redis数据结构和操作

redis不只是一个简单的键(key)-值(value)数据库,实际上它是一个数据结构服务器,支持各种类型的值。也就是说,在传统的键-值数据库中,你把字符串键与字符串值联系起来,而在redis,值不仅限于一个简单的字符串,还可以是更复杂的数据结构。下面列出了所有redis支持的数据结构,下文会分别对这些结构进行介绍:

  • 二进制安全字符串
  • 队列(lists):基于插入顺序有序存储的字符串元素集合。主要是链式的list。
  • 集(sets):元素唯一的、无序的字符串元素集合。
  • 有序集(sorted sets):与sets相似,但是每个字符串元素都与一个被称为分数(score)的浮点数相关联。和sets不同的是,元素能够基于分数排序,因此可以检索某个范围内的元素(比如你可以查询前10个或后10个)。
  • 哈希(hashes):由域(fields)和值之间关系组成的映射。域和值都是字符串。这和Ruby或Python的哈希非常相似。

INCR 命令把字符串解析成一个整数,然后 +1 ,把得到的结果作为一个新值存进去。还有其它相似的命令: INCRBYDECRDECRBY 。从命令的实现原理上讲,这几个命令是相同的,只是有一点细微的差别。  
为什么说 INCR 是原子性的呢?因为即使是多个客户端对同一个键使用 INCR 命令,也不会形成竞争条件。举个例子,像这样的情况是不会发生的:客户端 1 读取到键是 10 ,客户端 2 也读到键值是 10 ,它们同时对它执行自增命令,最终得到的值是 11 。实际上,最终的得到的值是 12 ,因为当一个客户端对键值做读 - 自增 - 写的过程中,其它的客户是不能同时执行这个过程的。  
有许多用于操作字符串的命令,例如 GETSET 命令,它给键设置一个新值,并返回旧值。比如你有一个系统,每当有一个新的访问者登陆你的网站时,使用 INCR 对一个键值自增。你可能想要统计每个小时的信息,却又不希望丢失每次自增操作。你可以使用 GETSET 命令,设置一个新值 “0” ,同时读取旧值。  \

\

键的生命周期

在介绍更多更复杂的数据结构之间,我们先讨论另一个与值类型无关的特性,那就是redis的期限(redis expires)。最基本的,你可以给键设置一个超时时间,就是这个键的生存周期。当生存周期过去了,键会被自动销毁,就好像被用户执行过DEL一样。 
一些关于redis期限的快速信息:

  • 生存周期可以设置的时间单位从秒级到毫秒级。
  • 生存周期的时间精度都是1毫秒。
  • 关于生存周期的数据有多份且存在硬盘上,基于Redis服务器停止了,时间仍在流逝,这意味着redis存储的是key到期的时间。

设置生存周期是件琐碎的事情:

> setkey some-value

OK

> expire key5

(integer)1

> getkey (immediately)

"some-value"

> getkey (after sometime)

(nil)

键在两次调用之间消失了,这是因为第二次调用的延迟了超过 5 秒的时间。在上面的例子中,我们使用 EXPIRE 命令设置生命周期(它也可以用于为一个已经设置过生命周期的键重新设置生命周期, PERSIST 命令可以用于移除键的命令周期,使它能够长期存在)。我们还可以使用 redis 命令在创建键的同时设置生命周期。\

1. 使用redis有哪些好处?

(1) 速度快,因为数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1)

(2) 支持丰富数据类型,支持string,list,set,sorted set,hash

(3) 支持事务,操作都是原子性,所谓的原子性就是对数据的更改要么全部执行,要么全部不执行

(4) 丰富的特性:可用于缓存,消息,按key设置过期时间,过期后将会自动删除

2. redis相比memcached有哪些优势?

(1) memcached所有的值均是简单的字符串,redis作为其替代者,支持更为丰富的数据类型

(2) redis的速度比memcached快很多

(3) redis可以持久化其数据

3. redis常见性能问题和解决方案:

(1) Master最好不要做任何持久化工作,如RDB内存快照和AOF日志文件

(2) 如果数据比较重要,某个Slave开启AOF备份数据,策略设置为每秒同步一次

(3) 为了主从复制的速度和连接的稳定性,Master和Slave最好在同一个局域网内

(4) 尽量避免在压力很大的主库上增加从库

(5) 主从复制不要用图状结构,用单向链表结构更为稳定,即:Master <- Slave1 <-Slave2 <- Slave3...

这样的结构方便解决单点故障问题,实现Slave对Master的替换。如果Master挂了,可以立刻启用Slave1做Master,其他不变。

4. mySQL里有2000w数据,redis中只存20w的数据,如何保证redis中的数据都是热点数据

 相关知识:redis内存数据集大小上升到一定大小的时候,就会施行数据淘汰策略。redis 提供 6种数据淘汰策略:

voltile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰

volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰

volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰

allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰

allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰

no-enviction(驱逐):禁止驱逐数据

5.Memcache与Redis的区别都有哪些?

1)、存储方式

Memecache把数据全部存在内存之中,断电后会挂掉,数据不能超过内存大小。

Redis有部份存在硬盘上,这样能保证数据的持久性。

2)、数据支持类型

Memcache对数据类型支持相对简单。

Redis有复杂的数据类型。

3)、使用底层模型不同

它们之间底层实现方式 以及与客户端之间通信的应用协议不一样。

Redis直接自己构建了VM机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求。

4),value大小

redis最大可以达到1GB,而memcache只有1MB

\

\

Redis集群架构

\

redis集群主要分为4种

第一种是客户端分片

需要自己实现分片的代码,不能平滑动态添加节点,添加节点需要手工修改代码实现。

第二种是Twemproxy\

Twitter推出的一种redis分布式框架,Twemproxy通过引入一个代理层,将多个Redis实例进行统一管理,使Redis客户端只需要在Twemproxy上进行操作,而不需要关心后面有多少个Redis实例,从而实现了Redis集群。

第三种是Codis

豌豆荚推出的分布式框架,Codis,一个支持平滑增加Redis实例的Redis代理软件,其基于Go和C语言开发,并于2014年11月在GitHub上开源。

第四种是Redis官方自己的Redis cluster

redis3.0以后推出的分布式集群框架,Redis 3.0集群采用了P2P的模式,完全去中心化。Redis把所有的Key分成了16384个slot,每个Redis实例负责其中一部分slot。集群中的所有信息(节点、端口、slot等),都通过节点之间定期的数据交换而更新。

\

\

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

\

\

\

\

\

\

\

\

\

\

然后给大家推荐几本提高篇的书籍:

1、jvm虚拟机

2、高性能mysql

3、MySQL技术内幕  InnoDB存储引擎  第2版

4、shell脚本编程

5、Java核心技术卷一和卷二

6、数据库索引设计与优化

\