平衡二叉树+双向链表=B+树
非叶子节点只存索引值,在最后一列也就是叶子节点的高度1上,存放行记录,这种在叶子节点存放整行记录的索引成为聚簇索引。
这种数据结构查询时间复杂度O(logn),千万级的数据通过索引往往只需3次IO就能查到。
MultiVersion Concurrency Control多版本并发控制,一般是对数据库并发访问,在编程语言中实现事务内存
数据库ACID(atomic,consistent, isolation,duration)
read uncommitted
read committed
repeatable read
serializable
从数据库系统角度看:
排他锁(写锁):当一个事务为数据加上写锁时,其他事务不能对其加任何锁,直到写锁释放,写锁的目的是在修改数据时候,不允许其他人读取和修改,避免脏数据问题
共享锁(读锁):当一个事务对数据加上读锁后,其他事务只能对该数据加读锁,知道所有读锁释放后,别的事务才能加写锁,读锁主要为了支持并发的读取数据,读取时不能被修改
从编写代码角度看:
悲观锁pessimistic concurrency control (pcc):
悲观的认为每次都会发生并发冲突,在可能出现并发的地方加上锁机制,按串行化处理
指数据被外界修改保持悲观,在整个数据处理过程中保持锁定。优点:数据处理安全,缺点:性能低、有o额外开销、有死锁可能
例子:在select后面加for update就是加了排他锁(写锁)
mysqlselect * from user for update;
**乐观锁optimisticconcurrency control (occ) **:
乐观的认为每次都不会发生并发冲突
mysqlSELECT * FROM table_name WHERE ... LOCK IN SHARE MODE
场景: 乐观锁适用多读场景(写比较少),悲观锁适用多写(读比较少)
应用中进程需要独占资源,如独占某个对象,当进程并发执行时可能会出现进程永远被阻塞现象,如两个进程分别等待对方所占资源,造成两者都不能执行下去处于永远等待状态成称为死锁
解决:重启;进程撤销:cpu消耗时间最少者、预计剩余执行时间最长者、
mysqlshow_query_log
开启:`
mysqlset global slow_query_log = 1;
查询慢sql日志存放路径
mysqlshow_query_log_file
是否记录未使用所有的sql
mysqllog_queries_not_using_indexes
remote dictionary server
场景:
充当缓存系统,为热点数据(读多写少)
计数器、限流器:限制一个手机发多少条短信、一个接口一分钟限制多少请求、一天内限制请求次数
消息队列系统、排行榜、社交网络、实时性高的系统(共享session、分布式锁)
限时业务:限时优惠活动、手机验证码
缓存、数据共享分布式、分布式锁、全局 ID、计数器、限流、购物车、消息队列、抽奖、点赞、签到、打卡等场景。
当redis获取某一个key时,由于key失效或不存在,向DB请求称为redis击穿
引发击穿原因:第一次访问、恶意访问不存在的key、key过期
规避方案:
服务启动时,提前写入:
规范key命名,通过中间件拦截
对高频key,设置ttl永不过期,或者过期时间设置成加上随即数
业务查询的数据既不在redis也不在DB,成为穿透
redis缓存层由于大量数据同时过期、redis故障宕机,所有请求都涌向储存层,短时高并发请求可能导致储存层宕机,
引起一系列连锁反应,造成整个系统崩溃
称之为redis雪崩,redis击穿是redis雪崩的一个子集
规避方案:对于大量数据同时过期:均匀的设置过期时间、互斥锁、双key策略、后台更新缓存
对于redis故障宕机:服务熔断、请求限流机制,使用redis高可用集群