常见面试题
常见面试题Object的finalize()方法的作用是否与C++的析构函数作用相同finalize()方法垃圾回收器准备释放内存的时候,会先调用finalize()。
与C++的析构函数不同,析构函数调用确定,而它的是不确定的
当对象变成(GC Roots)不可达时,GC会判断该对象是否覆盖了finalize方法,若未覆盖,则直接将其回收。否则,若对象未执行过finalize方法,将其放入F-Queue队列,由一低优先级线程执行该队列中对象的finalize方法。执行finalize方法完毕后,GC会再次判断该对象是否可达,若不可达,则进行回收,否则,对象“复活”。
方法执行随时可能被终止
给与对象最后一次重生的机会
对象不一定会被回收。
垃圾回收不是析构函数。
垃圾回收只与内存有关。
垃圾回收和finalize()都是靠不住的,只要JVM还没有快到耗尽内存的地步,它是不会浪费时间进行垃圾回收的。
Java中的强引用,软引用,弱引用,虚引用有什么用强引用
最普遍的引用:Object obj = new Object();
抛出OutOfMemoryError ...
Linux体系结构
Linux体系结构Linux
体系结构分为用户态和内核态
内核:本质上是一段管理计算机硬件设备的程序
系统调用:内核的访问接口,是一种不能再简化的操作
公用函数库:系统调用的组合拳
Shell:命令解释器,可编程
查找特定文件find12# 语法:find path [options] params
在指定目录下查找文件
示例:
1find / -name "target.java"
12# 以target开头 不区分大小写 支持正则表达式 find / -iname "target*"
检索文件内容grep12# 语法:grep [OPTION]... PATTERN [FILE]...
全称:Global Regular Expression Print
作用:查找文件里符合条件的字符串
示例:
12# 从target开头的文件中找包含moo的行grep "moo" target*
12# 通过正则表达式匹配(输入由管道输入)grep -o 'engin[0-9]*'
12 ...
Redis简介
Redis 简介缓存中间件——Memcache 与 Redis 的区别Memcache:代码层次类似Hash
支持简单数据库
不支持持久化
不支持主从
不支持分片
Redis
数据类型丰富
支持持久化
支持主从
支持分片
如果只是简单需要一个key-value缓存,则mencache即可,有高级要求则建议Redis
为什么Redis这么快Redis可以达到100000+QPS(Query per second,每秒查询次数)
完全基于内存,绝大部分请求是纯粹的内存操作,执行效率高
数据结构简单,对数据操作也简单
采用单线程,单线程也能处理高并发请求,想多核也可启动多实例
单线程指网络请求模块使用了一个线程(所以不需考虑并发安全性),即一个线程处理所有网络请求,其他模块仍用了多个线程。
单线程避免了频繁的上下文切换和锁竞争,也不会出现并发问题。
整个Redis肯定是多线程的,比如持久化写入时就开一个子线程去写入。
使用多路I/O复用模型,非阻塞I/O
客户端与服务端建立连接交由socket,可以同时建立多个连接(这里应该是多线程/多进程 ...
Redis常用数据类型
Redis 常用数据类型供用户使用的数据类型
String
最基本的数据类型,二进制安全(可以存任何数据,包括图像等)
值最大有512M
Hash
String元素组成的字典,适合用户存储对象
List
列表,按照String元素插入顺序排列
Set
String元素组成的无序集合,通过Hash表实现,不允许重复
Redis对Set提供了求交集并集等操作
Sorted Set(ZSet)
有序集合
每个元素会关联一个double类型的分数
通过分数为集合成员从小到大排序
用于计数的HyperLogLog
用于支持存储地理位置信息的Geo
KEYS pattern: 查找所有符合给定模式pattern的key
KEYS指令一次性返回所有符合条件的key
键的数量过大会使服务器卡顿
从海量key里查询某一固定前缀的keySCAN cursor [MATCH pattern] [COUNT count]
scan每次执行都只会返回少量元素 故可以用于生产环境,而不会带来keys命令的阻塞问题
基于游标的迭代器,需要基于上一次的游标延续之前的迭代过程
以 ...
持久化方式之RDB
持久化方式之RDBRDB(快照)持久化:保存某个时间节点的全量数据快照Redis配置文件在根目录下的redis.conf
配置文件中RDB相关信息
含义:900秒内有一条写入就产生快照,300秒内有10条写入就产生快照,以此类推
配置二:
设置成yes表示当备份进程出错的时候主进程就停止接受新的写入操作
配置三:
设置成yes就表示在备份时先压缩再保存,建议设置成no
RDB的创建与载入生成命令一:SAVE
阻塞Redis的服务进程,直到RDB文件被创建完毕(很少被使用)
生成命令二: BGSAVE
Fork一个子进程来创建RDB文件,不阻塞服务器进程
LASTSAVE返回上次保存的时间
自动化触发RDB持久化的方式
根据redis.conf文件中的配置来定时触发(用的BGSAVE)
主从复置时,主节点自动触发
执行Debug Reload时
执行Shutdown且没有开启AOF持久化
BGSAVE原理
执行 bgsave 命令,Redis 父进程判断当前是否存在正在执行的子进程,如 RDB/AOF 子进程,如果存在 bgsave 命令直接返回。
父进 ...
AOF持久化
AOF持久化AOF(Append-only-file)持久化:保存写状态
记录除查询以外所有变更数据库状态的指令
以append的形式将命令追加保存在AOF文件中(增量)
配置方法默认关闭,在配置文件中将appendonly no改为appendonly yes即可
配置写入方式:
always:一有变更就写入,everysec:每秒写入一次,no:交由操作系统决定,通常缓存区被填满了才写入。
日志重写解决AOF文件大小不断增大问题冗余命令可以精简,redis可以在后台重建AOF文件
调用fork,创建一个子进程
子进程把新的AOF文件写入临时文件,不依赖原来的AOF文件
主进程持续将新的变动同时写入内存和原来的AOF里
主进程获取子进程重写AOF完成信号,往新的AOF同步增量变动
使用新的AOF文件替换掉原来的AOF文件
RDB和AOF的优缺点
RDB优点:
全量数据快照,文件小,恢复快
RDB缺点:
无法保存最近一次快照之后的数据
AOF优点:
可读性高,适合保存增量数据,数据不易丢失
AOF缺点:
文件体积大,恢复时间长
RDB ...
Pipline及主从同步
Pipline和主从同步Pipline
Pipline和Linux管道类似
Redis基于请求/响应模型,单个请求处理需要一一作答
Pipline批量执行命令,节省多次I/O往返时间
有顺序依赖的指令建议分批发送
Redis同步机制主从同步原理
全量同步过程
Slave发送一个sync同步命令给Master要求全量同步。
Master接收到从服务的sync同步命令时,会fork一个子进程后台执行bgsave命令(非阻塞)快照保存,生成RDB文件。
Master将保存数据快照期间收到的写命令缓存起来
Mater完成写文件操作后将RDB文件发送给Slave
Slave将接收到的RDB文件载入自己的redis内存。
待Slave将RDB载入完成后,主服务再将缓冲区所有写命令发送给从服务。
从服务在将主服务所有的写命令载入内存从而实现数据的完整同步。
从服务下次在需要同步数据时只需要发送自己的offset位置(相当于MySQL binlog的位置)即可,只同步新增加的数据,再不需要全量同步。
增量同步过程
Master接收到用户的操作指令,判断是否需要传播到slave ...
Redis集群
Redis集群如何从海量数据里快速找到所需分片:按照某种规则划分数据,分散存储在多个节点上常规实现方法:按照哈希值与节点数取模来存储
无法实现节点动态增减
一致性Hash算法:
对2^ 32取模,将Hash值空间组织成虚拟圆环
对节点用同方法取Hash
对数据key用同方法算出Hash,算出key在环上的位置
数据key沿环行走,存储在找到的第一台节点中
节点宕机后数据被保存到下一个节点中去
新增节点后数据也会被相应重新保存
缺点
Hash环数据倾斜问题
解决办法:
引入虚拟节点,每个节点计算多个hash,每个hash位置放置一个虚拟节点
有序集合zset_跳表
redis有序集合zset的底层实现——跳跃表skiplist原理
上图用a,b,c,d,e五种有序链表及其变式(变式的名字是我随便起的)说明了跳跃表的motivation.
[a]单链表:查询时间复杂度O(n)[b]level-2单链表:每隔一个节点为一个level-2节点,每个level-2节点有2个后继指针,分别指向单链表中的下一个节点和下一个level-2节点。查询时间复杂度为O(n/2)[c]level-3单链表:每隔一个节点为一个level-2节点,每隔4个节点为一个level-3节点,查询时间复杂度O(n/4)[d]指数式单链表:每2^i个节点的level为i+1,查询时间复杂度为O(log2N)[e]跳跃表:各个level的节点个数同指数式单链表,但出现的位置随机,查询复杂度仍然是O(log2N)吗
当数据较少时,sorted set是由一个ziplist来实现的。 当数据多的时候,sorted set是由一个dict + 一个skiplist来实现的。简单来讲,dict用来查询数据到分数的对应关系,而skiplist用来根据分数查询数据(可能是范 ...
spring家族
Spring 家族Spring常见问题总结