diff --git a/Rocket.md b/Rocket.md index f480ff2..aaff4fc 100644 --- a/Rocket.md +++ b/Rocket.md @@ -82,6 +82,19 @@ Redis中setnx不支持设置过期时间,做分布式锁时要想避免某一 传统的LRU是使用栈的形式,每次都将最新使用的移入栈顶,但是用栈的形式会导致执行select *的时候大量非热点数据占领头部数据,所以需要改进。Redis每次按key获取一个值的时候,都会更新value中的lru字段为当前秒级别的时间戳。Redis初始的实现算法很简单,随机从dict中取出五个key,淘汰一个lru字段值最小的。在3.0的时候,又改进了一版算法,首先第一次随机选取的key都会放入一个pool中(pool的大小为16),pool中的key是按lru大小顺序排列的。接下来每次随机选取的keylru值必须小于pool中最小的lru才会继续放入,直到将pool放满。放满之后,每次如果有新的key需要放入,需要将pool中lru最大的一个key取出。淘汰的时候,直接从pool中选取一个lru最小的值然后将其淘汰。 +### Redis如何发现热点key + +1. 凭借经验,进行预估:例如提前知道了某个活动的开启,那么就将此Key作为热点Key。 +2. 服务端收集:在操作redis之前,加入一行代码进行数据统计。 +3. 抓包进行评估:Redis使用TCP协议与客户端进行通信,通信协议采用的是RESP,所以自己写程序监听端口也能进行拦截包进行解析。 +4. 在proxy层,对每一个 redis 请求进行收集上报。 +5. Redis自带命令查询:Redis4.0.4版本提供了redis-cli –hotkeys就能找出热点Key。(如果要用Redis自带命令查询时,要注意需要先把内存逐出策略设置为allkeys-lfu或者volatile-lfu,否则会返回错误。进入Redis中使用config set maxmemory-policy allkeys-lfu即可。) + +### Redis的热点key解决方案 + +1. 服务端缓存:即将热点数据缓存至服务端的内存中.(利用Redis自带的消息通知机制来保证Redis和服务端热点Key的数据一致性,对于热点Key客户端建立一个监听,当热点Key有更新操作的时候,服务端也随之更新。) +2. 备份热点Key:即将热点Key+随机数,随机分配至Redis其他节点中。这样访问热点key的时候就不会全部命中到一台机器上了。 + ### 如何解决 Redis 缓存雪崩问题 1. 使用 Redis 高可用架构:使用 Redis 集群来保证 Redis 服务不会挂掉 @@ -181,6 +194,13 @@ SQL的执行顺序:from---where--group by---having---select---order by 4. binlog不是循环使用,在写满或者重启之后,会生成新的binlog文件,redolog是循环使用。 5. binlog可以作为恢复数据使用,主从复制搭建,redolog作为异常宕机或者介质故障后的数据恢复使用。 +### Mysql读写分离以及主从同步 + +1. 原理:主库将变更写binlog日志,然后从库连接到主库后,从库有一个IO线程,将主库的binlog日志拷贝到自己本地,写入一个中继日志中,接着从库中有一个sql线程会从中继日志读取binlog,然后执行binlog日志中的内容,也就是在自己本地再执行一遍sql,这样就可以保证自己跟主库的数据一致。 +2. 问题:这里有很重要一点,就是从库同步主库数据的过程是串行化的,也就是说主库上并行操作,在从库上会串行化执行,由于从库从主库拷贝日志以及串行化执行sql特点,在高并发情况下,从库数据一定比主库慢一点,是有延时的,所以经常出现,刚写入主库的数据可能读不到了,要过几十毫秒,甚至几百毫秒才能读取到。还有一个问题,如果突然主库宕机了,然后恰巧数据还没有同步到从库,那么有些数据可能在从库上是没有的,有些数据可能就丢失了。所以mysql实际上有两个机制,一个是半同步复制,用来解决主库数据丢失问题,一个是并行复制,用来解决主从同步延时问题。 +3. 半同步复制:semi-sync复制,指的就是主库写入binlog日志后,就会将强制此时立即将数据同步到从库,从库将日志写入自己本地的relay log之后,接着会返回一个ack给主库,主库接收到至少一个从库ack之后才会认为写完成。 +4. 并发复制:指的是从库开启多个线程,并行读取relay log中不同库的日志,然后并行重放不同库的日志,这样库级别的并行。(将主库分库也可缓解延迟问题) + ### Next-Key Lock InnoDB 采用 Next-Key Lock 解决幻读问题。在`insert into test(xid) values (1), (3), (5), (8), (11);`后,由于xid上是有索引的,该算法总是会去锁住索引记录。现在,该索引可能被锁住的范围如下:(-∞, 1], (1, 3], (3, 5], (5, 8], (8, 11], (11, +∞)。Session A(`select * from test where id = 8 for update`)执行后会锁住的范围:(5, 8], (8, 11]。除了锁住8所在的范围,还会锁住下一个范围,所谓Next-Key。