redis:
缓存击穿:对于访问过期的key查询数据时,加锁,保证只有一个线程去底层获取数据,并返回结果缓存
缓存穿透:对于访问不存在的key时给出空结果并缓存,或引入布隆过滤器将数据提前缓存在布隆过滤器中
缓存雪崩:对于key采用随机过期时间,避免大量的key在同一时间失效导致数据库承载过高
持久化机制:
AOF:以追加 命令行记录的方式记录完整的日志 优点:能够完整恢复数据 缺点:恢复备份效率低
RDB:以二进制的方式定时本分数据 优点:恢复备份效率高 缺点:存在备份时间临界区有丢失数据的可能
AOF + RDB:定时备份数据以二进制的方式写入文件,增量以命令行的记录方式追加到文件当中
数据类型:
string : 字符串(操作命令:set get append setrange getrange strlen)
数值(操作命令:incr) 理解待加深
bitmap
list: 理解待加深
hash: 理解待加深
set: 理解待加深
sorted_set 理解待加深
并发编程:
synchronized (悲观锁,非公平锁 ) 与 lock(reetrantLock,readwriteLock)(非公平锁、乐观锁)
synchronized:1.6之前为重型锁:线程获取不到锁会直接进入(锁池)队列等待直到上一个线程释放锁之后才可以争取锁
1.6之后引入了锁升级概念:JAVA对象头部(MarkWord)包含锁的信息,锁升级状态由无锁到第一次加锁升级为偏向锁,第二次加锁发生锁竞争则升级为轻量级锁,轻量级锁通过CAS自旋尝试获取锁,如仍然获取不到锁则升级为重量级锁进入锁池等待即1.6之前的方式
reetrantLock:底层采用CAS+AQS方式实现的锁机制,当一个线程想要获取锁先通过CAS自旋方式尝试获取锁;如获取不到则将当前线程封装为Node对象并存入AQS双向队列中,
1:AQS双向队列中已有线程在等待则将当前线程挂接在已有线程后面并将指针互相连接上,且挂接成功后会将上一个Node节点的状态(waitStatus)更新为-1表示上一个Node节点后面挂接的Node节点可被唤醒,处于AQS队列的头部Node节点会通过CAS方式尝试获取锁资源
2:AQS双向队列中没有线程在等待,则会创建一个虚拟的头部节点(head)并将当前Node节点挂接在虚拟节点之后,且将虚拟头部节点(head)的状态(waitStatus)设置为-1,以便更高效率的唤醒后面的线程节点
readwriteLock:读读不互斥,读写互斥,写写互斥;与reetranLock的区别在于更在细化的对锁的颗粒度做了区别,以适用读、写的不同场景下的效率提升
concurrentHashMap:多线程并发的线程安全集合类;采用数组+单向链接+红黑树的数据结构 ,当数组长度大于64(实则为了优化效率,数组的查询时间复杂度为O(1))且单向链表长度大于8(优化效率,单向链接的查询时间复杂度为O(n))时单向链接将转化成红黑树结构(时间复杂度Ologn)
CAS:比较并交换;程序运行时会先从内存中获取数据到CPU进行计算,再将计算完的结果写入到内存
1:如果多个线程同一时间从内存中获取同一份的数据进行计算则会引发数据不一致性的问题(其他线程不能及时拿到某一线程计算完写入的内存中的数据)
2:因此CAS的方式就是数据在CPU计算完之后写入到内存时,会比较此时内存中的值与当前CPU中获取的值是否一致,如一致则认为没有其它的线程修改过值正常写入,反之就认为值被其它线程篡改过则写入失败,再次通过CAS自旋方式直到写入成功为止
Executors创建线程池的几种方式:
newFixedThreadPool:固定线程数的线程池,当添加的线程数超过定义的线程数时则进入阻塞队列(LinkedBlockingQueue),遵循FIFO(先进先出)原则等待线程池中有空闲的线程数时再 进行工作
newScheduledThreadPool:固定线程数的定时任务线程池,底层采用延迟队列(DelayedWorkQueue),可按固定的周期或者延迟多久的时间执行任务
newCachedThreadPool:创建存活时间为60秒的线程池,当前第一次有任务进来会直接创建新线程,如60秒内再次有任务进入会复用已创建的存活线程执行任务,如60秒内无任务进入则会结束当前线程池。如60秒外有任务进入则会创建新的线程执行;因为任务只要提交线程池中,就必然会有线程处理
newSingleThreadExecutor:单例线程池,线程池中只有一个线程在工作,后续进来的任务会进入到阻塞对列中等待,遵循FIFO(先进先出)原则,因此单例线程池适合按顺序执行的一系列任务
newWorkStealingPool:并行计算底层使用ForkJoinPool;核心思想分而治之,线程窃取;使用场景,将一个大的任务按照一定的规则拆分(需手动编写拆分逻辑) 并放到当前线程的阻塞队列当中,其它的空闲线程可以去处理有任务的线程的阻塞列队中的任务 ,优点:线程池中空闲线程可以被充分利用
线程数计算:
核心线程数=cpu核数 * cpu利用率 * (1 + w/c)=cpu核数 * (1-阻塞系数)
分布式
CAP:Consistency(一致性) Availability(可用性) Partition Tolerance(分区容错性)
微服务规定原则:CP / AP 三选二挑一
C:保证微服务之间的数据强一致性,如zookeeper 发送消息必须等待其它节点都有反馈结果才可成功
A:保证微服务之间的可用,如某个节点掉线(需返回错误响应结果)但其他节点可正常使用则不影响整体的服务调用流程
P:保证由于网络故障原因(网络不可靠运行)引起的服务波动不影响整体的系统运行,分布式系统的基石
nacos:阿里开源的微服务注册中心
服务注册:微服务调用注册中心客服端服务发送微服务实例信息完成注册
服务心跳:客户端会以默认5秒的频率向服务端发送心跳,告知注册中心当前服务的健康状态
服务健康检查:服务端启用定时任务默认每15秒检查一次注册服务列表的健康状态如超过25秒未响应则将服务置不健康状态并下线
服务发现:注册中心的服务能被其它服务检测到且可调用
服务同步:CP
Mysql
b+tree:矮胖形的树状结构;
1:非子叶节点存储子叶节点的分区指针信息不存储数据
2:子叶节点存储主键信息(如有主键存储主键列信息,否则存储唯一索引列信息,两者都未生成则会存储生成隐式的rowid)
联合索引:多列组合创建的索引;
1:最左前缀原则:where 条件中必须包第一列的字段才会生效且需正确命中索引
2:原理:多列联合索引先按第一列构建b+tree结构,第二列基于第一列再构建b+tree索引以此类推,因此第一列未命中索引,第二例自然不会命中索引
3:回表查询:对于普通索引(二级索引,非聚簇索引),构建b+tree不会存储该列数据,而是存储主键对应的指针引用,所以普通索引查询时先从主键索引中找到对应的主键再根据主键查询返回完整数据 待加深理解