关于面试的那点事
\
最近去面了挺多公司了
\
楼主是java后端三年工作经验,去面试的职位是高级java工程师,闲话不多说,直接上面试的一些大纲。
博客主要的讲解了一下大纲,具体的细节大家可以访问下面网址去下载对应的详细介绍。
download.csdn.net/detail/tian…\
链接地址是csdn下载资源,包含了详细的面试题目和一些学习知识点,已经被1000多人下载。
下面是百度网盘地址:新加了很多面试内容
\
由于最近比较忙,所以博客写的比较简单,更多内容详见百度网盘下载地址和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 ,把得到的结果作为一个新值存进去。还有其它相似的命令: INCRBY , DECR, DECRBY 。从命令的实现原理上讲,这几个命令是相同的,只是有一点细微的差别。
为什么说 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、数据库索引设计与优化
\