1.线程数怎么设置比较合适,为什么要有最大线程数
CPU密集型N+1,IO密集型2N,最大线程要在等待队列跑完以后才执行,核心线程数是不销毁的,最大线程要等队列满了才创建,执行完后一段时间未调用会销毁
2.几种代理模式的区别,怎么实现比较好
cglib运行时效率更高,jdk模式创建时效率更高,单例或无需频繁创建的实例池,用cglib,反之用jdk
3.Mysql的索引数据结构有什么
Hash索引:原理和jdk的hashmap类似,缺点是不能范围查询
B-树索引:节点即存放key也存放data
B+树索引:只有叶子节点存放data,其他节点只存放key
B+树的磁盘读写代价更低
B+树的内部结点并没有指向关键字具体信息的指针。因此其内部结点相对B树更小。如果把所有同一内部结点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多。一次性读入内存中的需要查找的关键字也就越多。相对来说I/O读写次数也就降低了。
B+树的查询效率更加稳定
由于内部结点并不是最终指向文件内容的结点,而只是叶子结点中关键字的索引。所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同,导致每一个数据的查询效率相当。
B+树更有利于对数据库的扫描
B树在提高了磁盘IO性能的同时并没有解决元素遍历的效率低下的问题,而B+树只需要遍历叶子节点就可以解决对全部关键字信息的扫描,所以对于数据库中频繁使用的range query,B+树有着更高的性能
4.消息队列,怎么保证数据不丢失
生产端:
Producer 的retries设置次数增加,且要使用回调函数
消费端:
记录偏移量,关闭自动提交,手动提交偏移量
Kafka端:
设置 acks = all
解决办法就是我们设置 acks = all。acks 是 Kafka 生产者(Producer) 很重要的一个参数。
acks 的默认值即为1,代表我们的消息被leader副本接收之后就算被成功发送。当我们配置 acks = all 代表则所有副本都要接收到该消息之后该消息才算真正成功被发送。
设置 replication.factor >= 3
为了保证 leader 副本能有 follower 副本能同步消息,我们一般会为 topic 设置 replication.factor >= 3。这样就可以保证每个 分区(partition) 至少有 3 个副本。虽然造成了数据冗余,但是带来了数据的安全性。
设置 min.insync.replicas > 1
5、Redis集群怎么搭建
三种模式
1、主从模式
一个节点为主节点,其他节点为从节点,可以实现读写分离,单节点宕机也保证可用性,缺点是主阶段宕机需要人为干预去选出新的主节点
2、哨兵模式
基于主从模式,增加了哨兵进程用于监控主节点情况,当多个哨兵认定主节点挂掉了,就自动选举出一个从节点作为新的主节点。但和主从一样多个主从间存储的都是相同的数据
3、集群模式
去中心化,采用多主多从,每个分区存储不同数据,客户端直连,只需要连接任意一个节点,每个分区都有全量插槽数据,通过计算插槽可得知数据具体在哪个节点,并连接对应节点获取数据
- 支付场景高并发怎么处理
没查到太好的办法,但原则上是数据库分库分表,主从结构,使用分布式ID,雪花算法,异步处理,保证数据最终一致性
亲手搭建redis,kafka,zookeeper环境
7.分布式锁
1.zookeeper实现
(1)利用节点名称创建唯一共享锁,加锁时所有客户端一起创建/test/Lock节点,只有一个能成功并获取锁,解锁时删除/test/Lock节点,其余客户端继续竞争,直到全部客户端都获取锁
(2)利用临时顺序节点创建唯一共享锁,所有客户端都去/test下创建节点,如果创建的客户端发现自己创建的是最小节点,就获取锁,否则监视比自己小的节点,进入等待,比如创建节点,/lock/0000000001、/lock/0000000002、/lock/0000000003。则节点/lock/0000000001会先获得锁,因为zk上的节点是有序的,且都是最小的节点先获得锁。
临时顺序节点比持久顺序节点的好处是:当zookeeper宕机后,临时顺序节点会自动删除,获取锁的客户端会释放锁,不会一直造成锁等待,而持久节点会造成锁等待。
方案一会产生惊群效应,当锁释放后所有客户端都会被唤醒,然后竞争分布式锁
方案二避免了惊群,按顺序唤醒
2.redis实现分布式锁
setnx(set if not exist):当不存在key时,才为key设置value。而set会直接覆盖value
getset:根据key得到旧的值,并设置新的值,用于获取过期时间,如果已经过期则设置新的过期时间并获得锁
expire:设置过期时间
del:删除
实现方式:
(1)获取锁的时候,使用setnx加锁,并使用expire设置过期时间,超过该时间自动释放锁,锁的value为一个随机生成的UUID,通过此UUID来释放锁
(2)获取锁的时候还设置一个获取的超时时间,若超时则放弃锁
(3)释放锁时需判断UUID,若是该锁则使用delete进行删除
3.数据库实现分布锁
实现方式:利用乐观锁和悲观锁
乐观锁:表中添加版本号的字段,更新前查版本号,更新时检查版本号,一致则更新,不一致则回退
悲观锁:select…for update,更新时锁表,需要关闭数据库自动提交
8.分布分表
分库分表的原因:
磁盘IO瓶颈:热点数据过多,数据库缓存放不下,查询产生大量IO,降低查询速度(分库,垂直分表)
网络IO瓶颈:请求的数据太多,网络带宽不够(分库)
CPU瓶颈:SQL语句慢,单表数据量大(水平分表,sql优化)
水平分库:以字段为依据,按照一定策略(hash,range等),将一个库的数据拆分到多个库中。每个库的结构都一样,每个库的数据都不同,所有库的数据为全量数据
水平分表:以字段为依据,按照一定策略(hash,range等),将一个表的数据拆分到多个表中。每个表的结构都一样,每个表的数据都不同,所有表的数据为全量数据
垂直分库:以表为依据,按照业务归属不同,将不同表拆分到不同库中。每个库的结构都不同,数据也不一样
垂直分表:以字段为依据,按照字段的活跃性,将表中字段拆分到不同表中。每个表的结构都不一样,每个表的数据也不一样
分库分表步骤:根据容量评估分库分表个数——选择key——分表规则(hash或range)——执行(一般双写)——扩容问题
分库分表工具:ShardingSphere
9.什么是Hash
输入不定长度的数据,得到固定长度数据的一种算法,特点是不能从结果推导出运算过程
网友评论