pull/10/head
yuanguangxin 4 years ago
parent 431fd16187
commit de531145ac

@ -37,6 +37,16 @@ zk类似于linux中的目录节点树方式的数据存储即分层命名空
client端会对某个znode建立一个watcher事件当该znode发生变化时这些client会收到zk的通知然后client可以根据znode变化来做出业务上的改变等。
### zk实现分布式锁
zk实现分布式锁主要利用其临时顺序节点实现分布式锁的步骤如下
1. 创建一个目录mylock
2. 线程A想获取锁就在mylock目录下创建临时顺序节点
3. 获取mylock目录下所有的子节点然后获取比自己小的兄弟节点如果不存在则说明当前线程顺序号最小获得锁
4. 线程B获取所有节点判断自己不是最小节点设置监听比自己次小的节点
5. 线程A处理完删除自己的节点线程B监听到变更事件判断自己是不是最小的节点如果是则获得锁
## Redis
### 应用场景
@ -110,20 +120,43 @@ Redis中setnx不支持设置过期时间做分布式锁时要想避免某一
### Redis的持久化机制
Redis为了保证效率数据缓存在了内存中但是会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件中以保证数据的持久化。Redis的持久化策略有两种
1. RDB快照形式是直接把内存中的数据保存到一个dump的文件中定时保存保存策略。
当Redis需要做持久化时Redis会fork一个子进程子进程将数据写到磁盘上一个临时RDB文件中。当子进程完成写临时文件后将原来的RDB替换掉。
1. AOF把所有的对Redis的服务器进行修改的命令都存到一个文件里命令的集合。
1. RDB快照形式是直接把内存中的数据保存到一个dump的文件中定时保存保存策略。当Redis需要做持久化时Redis会fork一个子进程子进程将数据写到磁盘上一个临时RDB文件中。当子进程完成写临时文件后将原来的RDB替换掉。
2. AOF把所有的对Redis的服务器进行修改的命令都存到一个文件里命令的集合。
使用AOF做持久化每一个写命令都通过write函数追加到appendonly.aof中。aof的默认策略是每秒钟fsync一次在这种配置下就算发生故障停机也最多丢失一秒钟的数据。
缺点是对于相同的数据集来说AOF的文件体积通常要大于RDB文件的体积。根据所使用的fsync策略AOF的速度可能会慢于RDB。
Redis默认是快照RDB的持久化方式。对于主从同步来说主从刚刚连接的时候进行全量同步RDB全同步结束后进行增量同步(AOF)。
### Redis和memcached的区别
### Redis的事务
1. Redis 事务的本质是一组命令的集合。事务支持一次执行多个命令一个事务中所有命令都会被序列化。在事务执行过程会按照顺序串行化执行队列中的命令其他客户端提交的命令请求不会插入到事务执行命令序列中。总结说redis事务就是一次性、顺序性、排他性的执行一个队列中的一系列命令。
2. Redis事务没有隔离级别的概念批量操作在发送 EXEC 命令前被放入队列缓存,并不会被实际执行,也就不存在事务内的查询要看到事务里的更新,事务外查询不能看到。
3. Redis中单条命令是原子性执行的但事务不保证原子性且没有回滚。事务中任意命令执行失败其余的命令仍会被执行。
### Redis事务相关命令
1. watch key1 key2 ... : 监视一或多个key,如果在事务执行之前被监视的key被其他命令改动则事务被打断类似乐观锁
2. multi : 标记一个事务块的开始queued
3. exec : 执行所有事务块的命令一旦执行exec后之前加的监控锁都会被取消掉
4. discard : 取消事务,放弃事务块中的所有命令
5. unwatch : 取消watch对所有key的监控
### Redis和 memcached 的区别
1. 存储方式上memcache会把数据全部存在内存之中断电后会挂掉数据不能超过内存大小。redis有部分数据存在硬盘上这样能保证数据的持久性。
2. 数据支持类型上memcache对数据类型的支持简单只支持简单的key-value而redis支持五种数据类型。
3. 用底层模型不同它们之间底层实现方式以及与客户端之间通信的应用协议不一样。redis直接自己构建了VM机制因为一般的系统调用系统函数的话会浪费一定的时间去移动和请求。
4. value的大小redis可以达到1GB而memcache只有1MB。
### Redis的哨兵机制
哨兵是一个分布式系统,你可以在一个架构中运行多个哨兵进程,这些进程使用流言协议来接收关于Master是否下线的信息,并使用投票协议来决定是否执行自动故障迁移,以及选择哪个Slave作为新的Master。
每个哨兵会向其它哨兵、master、slave定时发送消息,以确认对方是否活着,如果发现对方在指定时间(可配置)内未回应,则暂时认为对方已挂(所谓的”主观认为宕机”)。
若“哨兵群“中的多数sentinel,都报告某一master没响应,系统才认为该master"彻底死亡"(即:客观上的真正down机),通过一定的vote算法,从剩下的slave节点中,选一台提升为master,然后自动修改相关配置。
### Redis并发竞争key的解决方案
1. 分布式锁+时间戳
@ -248,6 +281,53 @@ MySQL为了保证ACID中的一致性和持久性使用了WAL(Write-Ahead Logg
6. or操作有至少一个字段没有索引
7. 需要回表的查询结果集过大(超过配置的范围)
### explain命令概要
1. id:select选择标识符
2. select_type:表示查询的类型。
3. table:输出结果集的表
4. partitions:匹配的分区
5. type:表示表的连接类型
6. possible_keys:表示查询时,可能使用的索引
7. key:表示实际使用的索引
8. key_len:索引字段的长度
9. ref:列与索引的比较
10. rows:扫描出的行数(估算的行数)
11. filtered:按表条件过滤的行百分比
12. Extra:执行情况的描述和说明
### explain 中的 select_type查询的类型
1. SIMPLE(简单SELECT不使用UNION或子查询等)
2. PRIMARY(子查询中最外层查询查询中若包含任何复杂的子部分最外层的select被标记为PRIMARY)
3. UNION(UNION中的第二个或后面的SELECT语句)
4. DEPENDENT UNION(UNION中的第二个或后面的SELECT语句取决于外面的查询)
5. UNION RESULT(UNION的结果union语句中第二个select开始后面所有select)
6. SUBQUERY(子查询中的第一个SELECT结果不依赖于外部查询)
7. DEPENDENT SUBQUERY(子查询中的第一个SELECT依赖于外部查询)
8. DERIVED(派生表的SELECT, FROM子句的子查询)
9. UNCACHEABLE SUBQUERY(一个子查询的结果不能被缓存,必须重新评估外链接的第一行)
### explain 中的 type表的连接类型
1. system最快主键或唯一索引查找常量值只有一条记录很少能出现
2. constPK或者unique上的等值查询
3. eq_refPK或者unique上的join查询等值匹配对于前表的每一行(row),后表只有一行命中
4. ref非唯一索引等值匹配可能有多行命中
5. range索引上的范围扫描例如between/in
6. index索引上的全集扫描例如InnoDB的count
7. ALL最慢全表扫描(full table scan)
### explain 中的 Extra执行情况的描述和说明
1. Using where:不用读取表中所有信息仅通过索引就可以获取所需数据这发生在对表的全部的请求列都是同一个索引的部分的时候表示mysql服务器将在存储引擎检索行后再进行过滤
2. Using temporary表示MySQL需要使用临时表来存储结果集常见于排序和分组查询常见 group by ; order by
3. Using filesort当Query中包含 order by 操作,而且无法利用索引完成的排序操作称为“文件排序”
4. Using join buffer改值强调了在获取连接条件时没有使用索引并且需要连接缓冲区来存储中间结果。如果出现了这个值那应该注意根据查询的具体情况可能需要添加索引来改进能。
5. Impossible where这个值强调了where语句会导致没有符合条件的行通过收集统计信息不可能存在结果
6. Select tables optimized away这个值意味着仅通过使用索引优化器可能仅从聚合函数结果中返回一行
7. No tables usedQuery语句中使用from dual 或不含任何from子句
### 数据库优化指南
1. 创建并使用正确的索引
@ -344,6 +424,13 @@ JVM引入动态年龄计算主要基于如下两点考虑
3. 方法区空间不足
4. 通过Minor GC后进入老年代的平均大小大于老年代的可用内存
5. 由Eden区、From Space区向To Space区复制时对象大小大于To Space可用内存则把该对象转存到老年代且老年代的可用内存小于该对象大小
### 对象什么时候进入老年代
1. 大对象直接进入老年代。 虚拟机提供了一个阈值参数令大于这个设置值的对象直接在老年代中分配。如果大对象进入新生代新生代采用的复制算法收集内存会导致在Eden区和两个Survivor区之间发生大量的内存复制应该避免这种情况。
2. 长期存活的对象进入老年代。 虚拟机给每个对象定义了一个年龄计数器对象在Eden区出生经过一次Minor GC后仍然存活并且能被Survivor区容纳的话将被移动到Survivor区中此时对象年龄设为1。然后对象在Survivor区中每熬过一次 Minor GC年龄就增加1当年龄超过设定的阈值时就会被移动到老年代中。
3. 动态对象年龄判定: 如果在 Survivor 空间中所有相同年龄的对象,大小总和大于 Survivor 空间的一半,那么年龄大于或等于该年龄的对象就直接进入老年代,无须等到阈值中要求的年龄。
4. 空间分配担保: 如果老年代中最大可用的连续空间大于新生代所有对象的总空间,那么 Minor GC 是安全的。如果老年代中最大可用的连续空间大于历代晋升到老年代的对象的平均大小,就进行一次有风险的 Minor GC如果小于平均值就进行 Full GC 来让老年代腾出更多的空间。因为新生代使用的是复制算法,为了内存利用率,只使用其中一个 Survivor 空间来做轮换备份,因此如果大量对象在 Minor GC 后仍然存活,导致 Survivor 空间不够用,就会通过分配担保机制,将多出来的对象提前转到老年代,但老年代要进行担保的前提是自己本身还有容纳这些对象的剩余空间,由于无法提前知道会有多少对象存活下来,所以取之前每次晋升到老年代的对象的平均大小作为经验值,与老年代的剩余空间做比较。
### TLAB
@ -563,6 +650,13 @@ AQS有两个队列同步对列和条件队列。同步队列依赖一个双
6. threadFactory线程工厂用于创建线程一般用默认的即可。
7. handler拒绝策略。当任务太多来不及处理如何拒绝任务。
### 线程池的执行流程
1. 如果正在运行的线程数量小于 corePoolSize那么马上创建线程运行这个任务
2. 如果正在运行的线程数量大于或等于 corePoolSize那么将这个任务放入队列
3. 如果这时候队列满了,而且正在运行的线程数量小于 maximumPoolSize那么还是要创建非核心线程立刻运行这个任务
4. 如果队列满了,而且正在运行的线程数量大于或等于 maximumPoolSize那么线程池会抛出异常RejectExecutionException
### 线程池都有哪几种工作队列
1. ArrayBlockingQueue底层是数组有界队列如果我们要使用生产者-消费者模式,这是非常好的选择。

Loading…
Cancel
Save