11.redis持久化,RDB和AOF有什么区别
RDB持久化(效率优先):指定的时间间隔内fork一个子进程,先将数据集写入临时文件,写入成功后,再替换之前的文件,用二进制压缩存储。
优势:
1)数据都存储在一个文件中,便于灾难恢复。
2)不会对性能造成太大的影响,持久化是通过fork出子进程完成的,可以极大的避免服务进程执行IO操作。
3)当数据集较大时,启动效率高于AOF。
劣势:
1)定时持久化前宕机的话,没有保存的数据会全部丢失
2)由于是fork子进程来协助完成数据集持久化工作,当数据集较大时,可能会导致整个服务器停止服务。
AOF持久化(一致性优先):以日志的形式记录服务器所处理的每一个写、删除操作,保留详细的操作记录(格式清晰、易于理解)
优势:
1)数据安全性高,写入操作采用的是append模式,出现宕机现象,也不会破坏日志文件中已经存在的记录。
2)如果日志过大,Redis可以自动启用rewrite机制(以append模式将修改数据写入到老的磁盘文件中,同时会创建一个新的文件用于记录此期间有哪些修改命令被执行)。
3)可以根据日志文件完成数据重建:
劣势:
1)因为需要记录每条操作,文件会比RDB大,灾难恢复速度也会被较慢。
2)AOF运行效率会比RDB稍慢。
12.Redis部署模式有哪些?
主从模式:设置一个主节点,N个从节点,写主读从。必须保证主节点不会宕机,一旦主节点宕机,其它节点不会竞争成为主节点,Redis将丧失写的能力。
哨兵模式:比主从模式多了一个竞选机制,主节点宕机,所有的从节点会竞选出新的主节点。(依赖于在系统中启动一个sentinel进程)sentinel进程会监听主从之间是否正常工作,实例出了问题时会通过API通知。主节点出问题后,sentinel会在所有的从节点中竞选出一个节点,并将其作为新的主节点。它还能够向使用者提供当前主节点的地址,故障转移后使用者不用做任何修改就可以知道当前主节点地址。
cluster(集群)模式:自动分割数据到不同的节点上(集群有16384个哈希槽,每个key完成CRC16校验后对16384取模来决定放置哈希槽),主从复制模型,每个节点都会有N-1个复制品,整个集群的部分节点失败或者不可达的情况下能够继续处理命令。但是因为是集群使用了异步复制,所以不能保证数据的强一致性。
13.nosql是否了解?项目实际运用?
nosql泛指非关系型的数据库。
1)高性能,高可用性和可伸缩性
2)没有声明性查询语言(sql)
3)存储格式为键 - 值对存储(redis)、列式存储(HBase)、文档存储(MongDB)、图形数据库(Neo4j)
4)最终一致性,并非遵循ACID(原子、一致、隔离、持久)
数据库选型
1)数据量少,并发少建议选择关系型数据库
2)流量大系统后台建议关系型数据库
3)批量数据处理、离线计算、即时查询、监控,建议选列式存储
4)事务性系统建议选择关系型数据库
5)数据量很大或者未来会变得很大,且表结构不明确,且字段在不断增加,建议使用文档存储
6)关系性强、记录大量基于事件的数据、推荐引擎推荐使用图形数据库
14.tomcat集群怎么保证同步?
增量复制:只同步会话增量,集群中一个节点发生改变后,在一个请求被响应之前会同步到其余全部节点。但是因为备份的网络流量会随着节点数的增加而急速增加,无法构建较大规模集群。
绑定:每个会话只有一个备份,利用负载均衡的源地址Hash算法实现,整个会话期间,用户所有的请求都来自一台歌节点。(宕机会导致节点上的数据全部丢失)
15.如何解决超卖问题?
当商品库存接近0时,如果多个买家同时付款购买此宝贝,会出现超卖缺货的现象。
sql适合流量少的情况,秒杀的情况下,数据库扛不住:
排他锁
update goods set num = num - 1 WHERE id = 1001 and num > 0;
乐观锁
-
select version from goods where id = 1001;
-
update goods set num = num - 1, version = version + 1 WHERE id = 1001 AND num > 0 AND version = 1;
为什么通过新增字段version控制,而不是利用原有num字段?
存在ABA问题:A线程获取num为3,B线程获取num也为3,B线程先将num-1=2,处理失败又将库存数恢复成3,A线程在进行更新操作时num=3,但是操作期间num已经有了变化。
悲观锁
select * from goods where id = 1001 for update;
update goods set num = num - 1, version = version + 1 WHERE id= 1001;
redis:
锁 将商品数量放入缓存中,使用锁来处理其并发情况。当接到买家提交订单的情况下,先加锁,然后将商品数量递减,解锁后进行其他处理。如果处理失败加锁后将数据递增1再解锁。当商品数量递减到0时,表示商品秒杀完毕,拒绝其他用户的请求。
队列 Redis 队列中加入商品数量相等的元素,请求进入从队列上 pop 出一个元素,获得就代表成功。
异步:
将购买请求放入消息队列之中,异步处理结果。
16.分布式id生成方式
1)数据库自增
优势:
实现简单、自增方便排序
劣势:
分库分表、数据迁移的时候会出现问题,且难以扩展
2)uuid
优势:
实现简单、拥有唯一性,分库分表和数据迁移无影响
劣势:
没有排序,无法保证趋势递增,长度较长,存储、查询效率较低,作为id性能差
3)Redis的原子操作 INCR
优势:
性能好,递增保证排序
劣势:
需要引入redis,增加复杂度
4)snowflake算法(百度uid-generator和美团ecp-uid都是基于snowflake实现的)
使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID),最后还有一个符号位,永远是0
优势:
性能好、单机递增
劣势:
要求系统时间只能增不能减,无法应对时间回退(修改机器时间)问题(官方scala代码会对比时间,如果发生回退回抛InvalidSystemClock异常)
17.int的范围?
-2^31-2^31-1
18.java常用数据结构
List、Set、Map
19.ConcurrentHashMap
线程安全且高效的HashMap实现,数组+链表(链表节点数超过指定阈值8的话,也是会转换成红黑树)
Java 5 之后,引用了内部的 Segment ( ReentrantLock ) 分段锁,操作同段 map 的时候,进行锁的竞争和等待。
jdk8重新使用synchronized+cas
1)多个分段锁浪费内存空间,而且影响gc效率
2)同时map 在放入时竞争同一个锁的概率非常小,分段锁反而会造成更新等操作的长时间等待
20.ConcurrentHashMap扩容
1)如果新增节点之后,所在链表的元素个数达到了阈值 8,则会调用treeifyBin
方法把链表转换成红黑树。
2)如果数组长度n小于阈值MIN_TREEIFY_CAPACITY(
默认是64),则会调用tryPresize
方法把数组长度扩大到原来的两倍,并触发transfer
方法,重新调整节点的位置。
3)新增节点之后,当数组元素个数达到阈值时,会触发transfer
方法。
transfer
方法:
1)新建一个长度为2n的数组。
2)线程获取一个扩容子任务,设置当前处理子任务的下界并更新当前处理节点所在的索引位置。(每迁移一个元素,元素会被设置为ForwardingNode,方便迁移过程中get)
3)对子任务中的每个节点,扩容线程从后向前依次判断该节点是否已经转移,如果没有转移,则对该节点进行加锁,并且把节点对应的链表或红黑树迁移到新数组中。
4)如果线程处理的节点索引已经到达子任务的下界,则子任务执行结束,并尝试去领取新的子任务,若领取不到再判断当前线程是否是最后一个扩容线程,若是则最后扫描一遍数组,执行清理工作,否则直接退出。
转载:https://blog.csdn.net/zhangdx001/article/details/104907732