面试总结的问题

synchronized的用法

synchronized是Java中的一个关键字,是一种同步锁,修饰的对象有以下几种:
1、修饰一个代码块,被修饰的代码块称为同步语句块,其作用范围是括号括起来的代码,作用的对象是调用这个代码块的对象。
2、修饰一个方法,被修饰的方法称为同步方法,其作用范围是整个方法,作用的对象是调用这个方法的对象。
3、修饰一个静态的方法,其作用范围是整个静态方法,作用的对象是这个类的所有对象。
4、修饰一个类,其作用范围是synchronized后面括号括起来的部分,作用的对象是这个类的所有对象。

Redis哈希槽

https://blog.csdn.net/tianyeshiye/article/details/79600014

数据结构

https://blog.csdn.net/yeyazhishang/article/details/82353846
1、数组Array
2、栈 stack
3、队列 queue
4、链表 linked list
5、树 tree
6、散列表 hash
7、堆 heap
8、图 graph

三次握手四次挥手

https://blog.csdn.net/qq_38950316/article/details/81087809

jsp与servlet区别

https://blog.csdn.net/forward__/article/details/57079115

重定向和转发的区别,以及能到百度吗

https://blog.csdn.net/liubin5620/article/details/79922692
区别:
转发(forward)浏览器的地址栏不变,重定(Redirect)向浏览器的地址栏改变。
转发是服务器行为,重定向是客户端行为。
转发是浏览器只做一次访问请求。重定向浏览器至少做两次访问请求。
转发两次跳转之间传输的信息不会丢失,重定向两次跳转之间传递的信息会丢失。
转发和重定向的选择:
1、重定向的速度比转发慢,因为浏览器还要发出一个新的请求,如果在使用转发和重定向都无所谓的情况下,建议使用转发。
2、因为转发只能访问当前web的应用程序,所以不同web应用程序之间的访问,特别是要访问到另一个web站点上资源的情况,就只能使用重定向了。

MAP遍历的方式

一、在键值都需要的时候使用

Map<Integer, Integer> map = new HashMap<Integer, Integer>(); 
for (Map.Entry<Integer, Integer> entry : map.entrySet()) { 
  System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue()); 
}

二、在for each循环中遍历keys和values
如果只需要map中的键或者值,可以通过keySet或values来实现遍历。

Map<Integer, Integer> map = new HashMap<Integer, Integer>(); 
//遍历map中的键 
for (Integer key : map.keySet()) { 
  System.out.println("Key = " + key); 
} 
//遍历map中的值 
for (Integer value : map.values()) { 
  System.out.println("Value = " + value); 
}

三、使用iterator遍历。

Map<Integer, Integer> map = new HashMap<Integer, Integer>(); 
Iterator<Map.Entry<Integer, Integer>> entries = map.entrySet().iterator(); 
while (entries.hasNext()) { 
  Map.Entry<Integer, Integer> entry = entries.next(); 
  System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue()); 
}

这种方式看起来冗余,却有其优点所在,首先在老版本Java中这是唯一遍历map的方式,同时可以在遍历map的同时使用iterator.remove()来删除数据。
四、通过键找值遍历

Map<Integer, Integer> map = new HashMap<Integer, Integer>(); 
for (Integer key : map.keySet()) { 
  Integer value = map.get(key); 
  System.out.println("Key = " + key + ", Value = " + value);

dubbo(※)

下次再问dubbo,一定给他吹出花来。
https://blog.51cto.com/13732225/2295896
调用关系说明:
1、服务容器负责启动、加载、运行服务提供者。
2、服务提供者在启动时,向注册中心注册自己提供的服务。
3、服务消费者在启动时,向注册中心订阅自己需要的服务。
4、注册中心提供服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
5、服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选择另一台进行调用。
6、服务消费者和提供者,在内存中累计调用次数和调用时间,定时没分组发送一次统计数据给监控中心。

官方推荐使用zookeeper注册中心,注册中心负责服务地址的注册与查找,相当于目录服务,服务提供者与消费者只在启动时与注册中心交互,注册中心不转发请求,压力较小。
面试题:
1、dubbo中,zookeeper作为注册中心,当zookeeper挂掉时,发布者和消费者之间还能互相通信吗?
可以的,dubbo启动时,消费者会总zk拉取生产者的地址接口等数据,缓存在本地,每次调用时,按照本地存储的地址进行调用。注册中心对等集群,一台挂掉之后,会自动切换到另一台,注册中心全部宕机,服务提供者和消费者仍可以通过本地缓存进行通讯。服务提供者无状态,任一台宕机后,不影响使用。服务提供者全部宕机,服务消费者会无法使用,并无限次重连等待服务提供者恢复。

zookeeper注册中心:
流程说明:
1、服务提供者启动时:向 /dubbo/com.foo.BarService/providers目录写下自己的URL地址。
2、服务消费者启动时:订阅/dubbo/com.foo.BarService/providers目录下服务提供者的URL地址,并向/dubbo/com.foo.BarService/consumers 目录写下自己的URL地址
3、监控中心启动时,订阅/dubbo/com.foo.BarService目录下所有的提供者和消费者URL地址。
支持以下功能:

  • 当提供者出现断电等异常停机时,注册中心能自动删除提供者信息。
  • 当注册中心重启时,能自动恢复注册数据,以及订阅请求。
  • 当会话过期时,能自动恢复注册数据,以及订阅请求。
  • 当设置 <dubbo:registry check=“false” /> 时,记录失败注册和订阅请求,后台定时重试
  • 可通过 <dubbo:registry username=“admin” password=“1234” /> 设置 zookeeper 登录信息
  • 可通过 <dubbo:registry group=“dubbo” /> 设置 zookeeper 的根节点,不设置将使用无根树
  • 支持 * 号通配符 <dubbo:reference group="" version="" />,可订阅服务的所有分组和所有版本的提供者

Redis的优缺点

为什么使用Redis,主要考虑性能与并发。
Redis的缺点:
1、缓存与数据库双写一致性问题。
一致性问题是分布式常见的问题,还可以分为最终一致性和强一致性。数据库和缓存双写,必然会存在数据不一致的情形。首先前提:如果要保证数据有强一致性要求,数据不能放缓存中,我们只能保证最终一致性。另外,我们所做的方案,从根本上来说只能降低不一致发生的概率,不能完全避免。
2、缓存雪崩问题。
即缓存同一时间内大面积失效,这时候又来了一批请求,全部到数据库上,从而导致数据库连接异常。
解决:

  • 给缓存的失效时间加上一个随机值,避免集体失效。

  • 使用互斥锁,但是该方案的吞吐量明显下降了。

  • 双缓存。我们有两个缓存,缓存A和缓存B。缓存A的失效时间为20分钟,缓存B不设失效时间。自己做缓存预热操作。然后细分以下几个小点

    I 从缓存A读数据库,有则直接返回
    II A没有数据,直接从B读数据,直接返回,并且异步启动一个更新线程。
    III 更新线程同时更新缓存A和缓存B。

3、缓存击穿问题。
即黑客故意去请求缓存中不存在的数据,导致所有的请求都到数据库上,从而数据库连接异常。
解决:

  • 采用互斥锁,缓存失效时,先去获得锁,得到锁之后再去请求数据库,没得到锁则休眠一段时间后重试。
  • 采用异步更新策略,无论key是否取到值,都直接返回。value值中维护一个缓存失效的时间,缓存如果过期,异步起一个线程去读数据库,更新缓存。
  • 提供一个能迅速判断请求是否有效的拦截机制。

4、缓存的并发竞争问题。
如果对这个key操作不要求顺序,这种情况下准备一个分布式锁,大家去抢锁,抢到锁就做set操作。
如果对这个key的操作要求顺序:
假设有一个key1,系统A需要将key1设置为valueA,系统B需要将key1设置为valueB,系统C需要将key1设置为valueC。期望key1的value值按照valueA,valueB,valueC的顺序去变化,这种时候在写入数据的时候,需要保存一个时间戳,如下
| 系统A | key1 | valueA 3:00 |
| 系统B | key1 | valueB 3:05 |
| 系统C | key1 | valueC 3:10 |
那么假设系统B先抢到锁,将key1设置为valueB 3:05,接下来系统A抢到锁,发现自己的valueA中的时间戳小于缓存中的时间戳,那么就不做set操作了。
其他方法,利用队列,将set方法变成串行访问也行。

单线程的Redis为什么这么快?
1、纯内存操作。
2、单线程操作,避免的频繁的上下文切换。
3、采用了非阻塞I/O多路复用机制。
Redis的五种基本数据类型:
1、String
2、list
3、set
4、hash
5、sorted set

MySql默认的锁,版本

数据库事务

事务就是逻辑上的一组sql语句操作,组成这组操作的各个sql语句,执行时要么全部成功要么全部失败。
事务的四大特性:
1、原子性
整个事务的所有操作,要么全部成功,要么全部不成功,不可能停滞在中间的某个环节。事务在执行过程中的某个环节出现错误会被回滚(rollback)到事务开始前的状态,就像这个事务没有执行过一样。
2、一致性
事务发生前和发生后,数据的完整性必须保持一致。
3、隔离性
多个并发事务之间的数据是相互隔离的。
4、持久性
一个事务一旦被提交,对数据库中数据的改变就是永久的,如果出现了错误,事务也不允许撤销。

分布式的优点

分表的优缺点

分布式负载均衡

线程池的优缺点,是越多越好吗?怎么定义数量?

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wmf_helloWorld

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值