1、基础知识
1.1 SpringBoot自动装配原理:
https://www.cnblogs.com/hhcode520/p/9450933.html
1.2 ConcurrentHashMap详解
https://www.cnblogs.com/yangming1996/p/8031199.html
1.3 Redis和Memcache区别,优缺点对比
1、 Redis和Memcache都是将数据存放在内存中,都是内存数据库。不过memcache还可用于缓存其他东西,例如图片、视频等等。
2、Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,hash等数据结构的存储。
3、虚拟内存–Redis当物理内存用完时,可以将一些很久没用到的value 交换到磁盘
4、过期策略–memcache在set时就指定,例如set key1 0 0 8,即永不过期。Redis可以通过例如expire 设定,例如expire name 10
5、分布式–设定memcache集群,利用magent做一主多从;redis可以做一主多从。都可以一主一从
6、存储数据安全–memcache挂掉后,数据没了;redis可以定期保存到磁盘(持久化)
7、灾难恢复–memcache挂掉后,数据不可恢复; redis数据丢失后可以通过aof恢复
8、Redis支持数据的备份,即master-slave模式的数据备份。
关于redis和memcache的不同,下面罗列了一些相关说法,供记录:
redis和memecache的不同在于[2]:
1、存储方式:
memecache 把数据全部存在内存之中,断电后会挂掉,数据不能超过内存大小
redis有部份存在硬盘上,这样能保证数据的持久性,支持数据的持久化(笔者注:有快照和AOF日志两种持久化方式,在实际应用的时候,要特别注意配置文件快照参数,要不就很有可能服务器频繁满载做dump)。
2、数据支持类型:
redis在数据支持上要比memecache多的多。
3、使用底层模型不同:
新版本的redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求。
4、运行环境不同:
redis目前官方只支持LINUX 上去行,从而省去了对于其它系统的支持,这样的话可以更好的把精力用于本系统 环境上的优化,虽然后来微软有一个小组为其写了补丁。但是没有放到主干上
个人总结一下,有持久化需求或者对数据结构和处理有高级要求的应用,选择redis,其他简单的key/value存储,选择memcache。
下面重点分析Memcached和Redis两种方案:
Memcached介绍
Memcached
是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提供动态、数据库驱动网站的速度,现在已被LiveJournal、hatena、Facebook、Vox、LiveJournal等公司所使用。
Memcached工作方式分析
许多Web应用都将数据保存到
RDBMS中,应用服务器从中读取数据并在浏览器中显示。 但随着数据量的增大、访问的集中,就会出现RDBMS的负担加重、数据库响应恶化、
网站显示延迟等重大影响。Memcached是高性能的分布式内存缓存服务器,通过缓存数据库查询结果,减少数据库访问次数,以提高动态Web等应用的速度、
提高可扩展性。下图展示了memcache与数据库端协同工作情况:
其中的过程是这样的:
1.检查用户请求的数据是缓存中是否有存在,如果有存在的话,只需要直接把请求的数据返回,无需查询数据库。
2.如果请求的数据在缓存中找不到,这时候再去查询数据库。返回请求数据的同时,把数据存储到缓存中一份。
3.保持缓存的“新鲜性”,每当数据发生变化的时候(比如,数据有被修改,或被删除的情况下),要同步的更新缓存信息,确保用户不会在缓存取到旧的数据。
Memcached作为高速运行的分布式缓存服务器,具有以下的特点:
1.协议简单
2.基于libevent的事件处理
3.内置内存存储方式
4.memcached不互相通信的分布式
如何实现分布式可拓展性?
Memcached的分布式不是在服务器端实现的,而是在客户端应用中实现的,即通过内置算法制定目标数据的节点,如下图所示: 
Redis 介绍
Redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、
list(链表)、set(集合)和zset(有序集合)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步,当前
Redis的应用已经非常广泛,国内像新浪、淘宝,国外像 Flickr、Github等均在使用Redis的缓存服务。
Redis 工作方式分析
Redis作为一个高性能的key-value数据库具有以下特征:
1.多样的数据模型
2.持久化
3.主从同步
Redis支持丰富的数据类型,最为常用的数据类型主要由五种:String、Hash、List、Set和Sorted
Set。Redis通常将数据存储于内存中,或被配置为使用虚拟内存。Redis有一个很重要的特点就是它可以实现持久化数据,通过两种方式可以实现数据持久化:使用RDB快照的方式,将内存中的数据不断写入磁盘;或使用类似MySQL的AOF日志方式,记录每次更新的日志。前者性能较高,但是可能会引起一定程度的数据丢失;后者相反。
Redis支持将数据同步到多台从数据库上,这种特性对提高读取性能非常有益。
Redis如何实现分布式可拓展性?
2.8以前的版本:与Memcached一致,可以在客户端实现,也可以使用代理,twitter已开发出用于Redis和Memcached的代理Twemproxy 。
3.0
以后的版本:相较于Memcached只能采用客户端实现分布式存储,Redis则在服务器端构建分布式存储。Redis
Cluster是一个实现了分布式且允许单点故障的Redis高级版本,它没有中心节点,各个节点地位一致,具有线性可伸缩的功能。如图给出Redis
Cluster的分布式存储架构,其中节点与节点之间通过二进制协议进行通信,节点与客户端之间通过ascii协议进行通信。在数据的放置策略上,Redis
Cluster将整个 key的数值域分成16384个哈希槽,每个节点上可以存储一个或多个哈希槽,也就是说当前Redis
Cluster支持的最大节点数就是16384。 
综合结论
应该说Memcached和Redis都能很好的满足解决我们的问题,它们性能都很高,总的来说,可以把Redis理解为是对Memcached的拓展,是更加重量级的实现,提供了更多更强大的功能。具体来说:
1.性能上:
性能上都很出色,具体到细节,由于Redis只使用单核,而Memcached可以使用多核,所以平均每一个核上Redis在存储小数据时比
Memcached性能更高。而在100k以上的数据中,Memcached性能要高于Redis,虽然Redis最近也在存储大数据的性能上进行优化,但是比起 Memcached,还是稍有逊色。
2.内存空间和数据量大小:
MemCached可以修改最大内存,采用LRU算法。Redis增加了VM的特性,突破了物理内存的限制。
3.操作便利上:
MemCached数据结构单一,仅用来缓存数据,而Redis支持更加丰富的数据类型,也可以在服务器端直接对数据进行丰富的操作,这样可以减少网络IO次数和数据体积。
4.可靠性上:
MemCached不支持数据持久化,断电或重启后数据消失,但其稳定性是有保证的。Redis支持数据持久化和数据恢复,允许单点故障,但是同时也会付出性能的代价。
5.应用场景:
Memcached:动态系统中减轻数据库负载,提升性能;做缓存,适合多读少写,大数据量的情况(如人人网大量查询用户信息、好友信息、文章信息等)。
Redis:适用于对读写效率要求都很高,数据处理业务复杂和对安全性要求较高的系统(如新浪微博的计数和微博发布部分系统,对数据安全性、读写要求都很高)。
需要慎重考虑的部分
1.Memcached单个key-value大小有限,一个value最大只支持1MB,而Redis最大支持512MB
2.Memcached只是个内存缓存,对可靠性无要求;而Redis更倾向于内存数据库,因此对对可靠性方面要求比较高
3.从本质上讲,Memcached只是一个单一key-value内存Cache;而Redis则是一个数据结构内存数据库,支持五种数据类型,因此Redis除单纯缓存作用外,还可以处理一些简单的逻辑运算,Redis不仅可以缓存,而且还可以作为数据库用
4.新版本(3.0)的Redis是指集群分布式,也就是说集群本身均衡客户端请求,各个节点可以交流,可拓展行、可维护性更强大。
ref:
http://blog.163.com/sun_jian_zhang/blog/static/187804041201310795917333/?suggestedreading&wumii http://www.cnblogs.com/EE-NovRain/p/3268476.html http://www.open-open.com/lib/view/open1409643182369.html
1.4 LinkedHashMap 源码详细分析(JDK1.8)
https://segmentfault.com/a/1190000012964859
1.4.1 高并发编程系列:ConcurrentHashMap的实现原理(JDK1.7和JDK1.8)
https://baijiahao.baidu.com/s?id=1617089947709260129&wfr=spider&for=pc
1.5 用LinkedHashMap实现LRU算法
2、蚂蚁金服的一次面试经历分享!(一面、二面)
2.1 电话一面
1、自我介绍、自己做的项目和技术领域
2、项目中的监控:那个监控指标常见的有哪些?
3、微服务涉及到的技术以及需要注意的问题有哪些?
4、注册中心你了解了哪些?
5、consul 的可靠性你了解吗?
6、consul 的机制你有没有具体深入过?有没有和其他的注册中心对比过?
7、项目用 Spring 比较多,有没有了解 Spring 的原理?AOP 和 IOC 的原理
8、Spring Boot除了自动配置,相比传统的 Spring 有什么其他的区别?
9、Spring Cloud 有了解多少?
10、Spring Bean 的生命周期
11、HashMap 和 hashTable 区别?
12、Object 的 hashcode 方法重写了,equals 方法要不要改?
13、Hashmap 线程不安全的出现场景
14、线上服务 CPU 很高该怎么做?有哪些措施可以找到问题
15、JDK 中有哪几个线程池?顺带把线程池讲了个遍
16、SQL 优化的常见方法有哪些
17、SQL 索引的顺序,字段的顺序
18、查看 SQL 是不是使用了索引?(有什么工具)
19、TCP 和 UDP 的区别?TCP 数据传输过程中怎么做到可靠的?
20、说下你知道的排序算法吧
21、查找一个数组的中位数?
22、你有什么问题想问我的吗?
在此我向大家推荐一个Java高级群 :725633148 里面会分享一些资深架构师录制的视频录像:(有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化、分布式架构、面试资料)等这些成为架构师必备的知识体系 进群马上免费领取,目前受益良多!
2.2 电话二面(85 分钟)
1、自我介绍、工作经历、技术栈
2、项目中你学到了什么技术?(把三项目具体描述了很久)
3、微服务划分的粒度
4、微服务的高可用怎么保证的?
5、常用的负载均衡,该怎么用,你能说下吗?
6、网关能够为后端服务带来哪些好处?
7、Spring Bean 的生命周期
8、xml 中配置的 init、destroy 方法怎么可以做到调用具体的方法?
9、反射的机制
10、Object 类中的方法
11、hashcode 和 equals 方法常用地方
12、对象比较是否相同
13、hashmap put 方法存放的时候怎么判断是否是重复的
14、Object toString 方法常用的地方,为什么要重写该方法
15、Set 和 List 区别?
16、ArrayList 和 LinkedList 区别
17、如果存取相同的数据,ArrayList 和 LinkedList 谁占用空间更大?
18、Set 存的顺序是有序的吗?
19、常见 Set 的实现有哪些?
20、TreeSet 对存入对数据有什么要求呢?
21、HashSet 的底层实现呢
22、TreeSet 底层源码有看过吗?
23、HashSet 是不是线程安全的?为什么不是线程安全的?
24、Java 中有哪些线程安全的 Map?
25、Concurrenthashmap 是怎么做到线程安全的?
26、HashTable 你了解过吗?
27、如何保证线程安全问题?
28、synchronized、lock
29、volatile 的原子性问题?为什么 i++ 这种不支持原子性?从计算机原理的设计来讲下不能保证原子性的原因
30、happens before 原理
31、cas 操作
32、lock 和 synchronized 的区别?
33、公平锁和非公平锁
34、Java 读写锁
35、读写锁设计主要解决什么问题?
36、你项目除了写 Java 代码,还有前端代码,那你知道前端有哪些框架吗?
37、MySQL 分页查询语句
38、MySQL 事务特性和隔离级别
39、不可重复读会出现在什么场景?
40、sql having 的使用场景
41、前端浏览器地址的一个 http 请求到后端整个流程是怎么样?能够说下吗?
42、http 默认端口,https 默认端口
43、DNS 你知道是干嘛的吗?
44、你们开发用的 ide 是啥?你能说下 idea 的常用几个快捷键吧?
45、代码版本管理你们用的是啥?
46、git rebase 和 merge 有什么区别?
47、你们公司加班多吗?
注:关注作者微信公众号,了解更多分布式架构、微服务、netty、MySQL、spring、JVM、算法、性能优化、面试等知识点。
公众号:《 Java大蜗牛 》
3 分布式架构系统拆分原则、需求、微服务拆分步骤
为什么需要应用拆分
我以淘宝技术架构演进为例,淘宝从一个大系统工程向分布式架构演变过程,你就能很清楚的知道为什么要需要进行应用拆分。
1 人员的角度。
维护一个代名工程Denali的百万级代码怪兽(虽然物理部署是分离的),从发布到上线,从人员的角度,百号人同时在一个工程上开发,一旦线上出问题,所有代码都需要回滚,从人员的角度,也基本忍受到了极致。
2 业务的角度
淘宝包含太多业务:用户、商品、交易、支付…等等,所有的代码早期都在denali一个工程里,代码已经严重影响到业务的效率,每个业务有各自的需求,需要给自己应用部署,各自开发需求。
3 从架构的角度
从数据库端oracle数据库集中式架构的瓶颈问题,连接池数量限制(oracle数据库大约提供5000个连接),数据库的CPU已经到达了极限90%。数据库端也需要考虑垂直拆分了。
4.急需走向一个大型的分布式时代,率先需要应用拆分。
1 )首先工程代码垂直拆分
把整个工程代码按照业务为单元进行垂直拆分。
淘宝按照业务为单位拆分成了类似这样的系统:UM(UserManger)、SM(ShopManager)..等等几十个工程代码。
2 )应用服务拆分
按照业务为单位,把所有调用相关的接口以业务为单元进行拆分。
比如,一个店铺系统,需要访问一个用户的头像的接口,用户头像的接口是独立部署在用户中心(UIC)这边的集群服务器上的。随着拆分的进行,淘宝的业务接口中心就变成了:UIC(用户中心服务)、SIC(店铺中心服务)等等以业务为单元部署的集群。
最终就演变成下图,按照业务为单位拆分和部署服务,用户中心、商品中心等:
总之,系统拆分是单体程序向分布式系统演变的关键一步,也是很重要的一步,拆分的好坏直接关系到未来系统的扩展性、可维护性和可伸缩性等,拆分工作不难理解,但是如何正确拆分、有什么样的方法和原则能帮助我们拆分得到一个我们理想中的系统:高可用、可扩展、可维护、可伸缩的分布式系统。
以下主要再从拆分需求、拆分原则和拆分步骤谈起:
拆分需求
1、组织结构变化:从最初的一个团队逐渐成长并拆分为几个团队,团队按照业务线不同进行划分,为了减少各个业务系统和代码间的关联和耦合,几个团队不再可能共同向一个代码库中提交代码,必须对原有系统进行拆分,以减少团队间的干扰。
2、安全:这里所指的安全不是系统级别的安全,而是指代码或成果的安全,尤其是对于很多具有核心算法的系统,为了代码不被泄露,需要对相关系统进行模块化拆分,隔离核心功能,保护知识产权。
3、替换性:有些产品为了提供差异化的服务,需要产品具有可定制功能,根据用户的选择自由组合为一个完整的系统,比如一些模块,免费用户使用的功能与收费用户使用的功能肯定是不一样的,这就需要这些模块具有替换性,判断是免费用户还是收费用户使用不同的模块组装,这也需要对系统进行模块化拆分。
4、交付速度:单体程序最大的问题在于系统错综复杂,牵一发而动全身,也许一个小的改动就造成很多功能没办法正常工作,极大的降低了软件的交付速度,因为每次改动都需要大量的回归测试确保每个模块都能正确工作,因为我们不清楚改动会影响到什么,所以需要做大量重复工作,增加了测试成本。这时候就需要对系统进行拆分,理清各个功能间的关系并解耦。
5、技术需求:
1)单体程序由于技术栈固定,尤其的是比较庞大的系统,不能很方便的进行技术升级,或者说对引入新技术或框架等处于封闭状态;每种语言都有自己的特点,单体程序没有办法享受到其它语言带来的便利;对应到团队中,团队技术相对比较单一。
2)相比于基于业务的垂直拆分,基于技术的横向拆分也很重要,使用数据访问层可以很好的隐藏对数据库的直接访问、减少数据库连接数、增加数据使用效率等;横向拆分可以极大的提高各个层级模块的重用性。
6、业务需求:由于业务上的某些特殊要求,比如对某个功能或模块的高可用性、高性能、可伸缩性等的要求,虽然也可以将单体整体部署到分布式环境中实现高可用、高性能等,但是从系统维护的角度来考虑,每次改动都要重新部署所有节点,显然会增加很多潜在的风险和不确定定性因素,所以有时候不得不选择将那些有特殊要求的功能从系统中抽取出来,独立部署和扩展。
如何拆分
1.拆分原则
- 单一职责
- 服务粒度适中
- 考虑团队结构
- 以业务模型切入
- 演进式拆分
- 避免环形依赖和双向依赖
2.分布式应用拆分实战
下面是拆分代码过程实践经验:
1). 设计module骨架module骨架的设计是基础,影响最终拆分结果,拆分成功的向导。按照技术,业务,部署打包,测试这几个维度来规划设计,下面是一个参考。 最终骨架模型层级: root web app webapp //war module,打包为单体war,整体部署 micro-services //微服务pom module user-service customer-service order-service other-service api-gateway biz //业务相关的module entitys //所有实体类 biz-base //一些无法拆分的代码上有依赖的服务 biz-user //用户业务 biz-customer //客户业务 biz-order //订单业务 … commons async-framework //一部框架 utils //工具类
2). 拆分技术commons
作为第一步,先对整个工程按业务和功能进行了maven多module的拆分。
首先是分离出技术上的commons,感觉这应该是最好拆分的了,把相关的类重构到一个包里,在分离出一个module即可。
3). 拆分entity
很多在业务代码上都会共享entity类,通常没法也没法把entity类分门别类,最简单就是把所有的entity类放到一个module,谁需要谁依赖的原则。entity类也没有太多jar依赖和业务依赖,也不会形成污染源。
4)公共业务
同commons和entity方法,不在复述,也被各个业务依赖,这种业务大部分是过渡性的,在未来迭代演进时可以通过其他方式抽象集成。
5)拆分业务代码
拆分业务是最痛苦的事情了,这个要看原来的代码整洁度和互相依赖程度,一般采取2中方法:
- 新建业务module,加入基础module的pom依赖,再从源module复制和该业务module相关的代码(包括单元测试代码)过来,解决编译错误和单元测试错误,完成本业务拆分。
- 从源module复制一个新业务module,保持代码一致,先删除和本义务无关的代码(包括单元测试代码),再删除无关的pom依赖,解决编译错误和单元测试错误,完成本业务拆分。
选择哪种方法,可以根据代码整洁度和互相依赖程度,如果代码很整洁且相互依赖较弱,可以采取前者,否则就采取后者。
6)拆分微服务
有了以上的拆分基础,可以在合适的业务迭代将各个微服务module迁移到不同的代码仓库,完成进一步隔离管理。
微服务架构框架

业界开源微服务架构框架提供了微服务的关键思路,例如 Dubbo 和 Spring Cloud(请关注后续文章,我会详解区别和优劣势)
Dubbo是Alibaba开源的分布式服务框架,它最大的特点是按照分层的方式来架构,使用这种方式可以使各个层之间解耦合(或者最大限度地松耦合)。
Spring Cloud是一个微服务框架,相比Dubbo等RPC框架, Spring Cloud提供的全套的分布式系统解决方案。
微服务架构是互联网技术发展的必然结果,它提倡将单一应用程序划分成一组小的服务,服务之间互相协调、互相配合,为用户提供最终价值。
分布式架构之应用拆分总结:
1.明确拆分原则和拆分需求。
2.梳理出业务模块和之间的依赖关联关系。
3.按照业务为单位,拆分实体、以及应用工程单独部署。
4.按照业务为单位拆分应用服务,避免环形依赖和双向依赖。
5.抽离出公用的接口、实体,以及服务单独部署为公用服务。
