Mysql事务日志undolog和redolog
https://www.cnblogs.com/f-ck-need-u/p/9010872.html
undo log有两个作用:提供回滚和多个行版本控制(MVCC)。如果因为某些原因导致事务失败或回滚了,可以借助该undo进行回滚。有时候应用到行版本控制的时候,也是通过undo log来实现的:当读取的某一行被其他事务锁定时,它可以从undo log中分析出该行记录以前的数据是什么,从而提供该行版本信息,让用户实现非锁定一致性读取。
undo log和redo log记录物理日志不一样,它是逻辑日志。可以认为当delete一条记录时,undo log中会记录一条对应的insert记录,反之亦然,当update一条记录时,它记录一条对应相反的update记录。
redolog用于重做,是物理日志,记录数据页的物理修改,用于恢复到最后一次提交的物理数据页。
LSN:LOG SEQUENCE NUMBER 日志序列号 ,redolog、数据页、checkpoint都有LSN,LSN是一个一直递增的整型数字,表示事务写入到日志的字节总量.
- update操作后 ,LSN增长到110,几乎同时在缓存中更新数据页和redolog的LSN
- 4处到达检查点checkpoint,检查点会同时触发数据页和redolog刷盘,并且有机制保护数据页刷盘速度慢于redolog的刷盘速度。
- 等到数据页和日志页刷盘完毕,即到了位置⑤的时候,所有的LSN都等于300。
- 位置⑥触发了redolog刷盘的规则,但此时buffer中的日志LSN和磁盘中的日志LSN是一致的,所以不执行日志刷盘.刷盘规则如下
- 发出commit动作时。已经说明过,commit发出后是否刷日志由变量 innodb_flush_log_at_trx_commit 控制。
- 每秒刷一次。这个刷日志的频率由变量 innodb_flush_log_at_timeout 值决定,默认是1秒。要注意,这个刷日志频率和commit动作无关
- 随后执行了提交动作,即位置⑧。默认情况下,提交动作会触发日志刷盘,但不会触发数据刷盘
在启动innodb的时候,不管上次是正常关闭还是异常关闭,总是会进行恢复操作。启动数据库时会检查磁盘中数据页的LSN,如果数据页的LSN小于日志中的LSN,则会从检查点开始根据 磁盘中的redolog恢复。
Redis
redis 数据存于内存中,因此读写速度快,用于缓存。还用于做分布式锁。
为什么用redis/缓存?
- 高性能 多次访问时,除了第一次从硬盘读取,之后都从内存读取,速度自然快很多。若数据库改变,同步改变缓存即可。
- 高并发 缓存能承受的请求数量远大于数据库
为什么要用 redis 而不用 map/guava 做缓存?
redis,memcached是分布式缓存,在多实例情况下,各实例共享一份缓存,缺点是要保证高可用,架构较复杂。Java的map/guava是本地是缓存,生命周期同jvm,各实例保存一份缓存。
redis 和memcached 的区别
-
四种常用IO模型
- 同步/非同步 && 阻塞/非阻塞的概念理解:
- 同步和异步仅仅是关注的消息如何通知的机制,而阻塞与非阻塞关注的是等待消息通知时的状态。也就是说,同步的情况下,是由处理消息者自己去等待消息是否被触发,而异步的情况下是由触发机制来通知处理消息者。阻塞时进程不能做别的事,处理其他IO,非阻塞是进程可以做别的事。
- 网络IO
- I/O一般包括两个步骤:
- 数据从网络到达,并将其复制到内核缓冲区
- 数据从内核缓冲区复制到进程缓冲区
- 同步阻塞模型:从应用程序执行系统调用recvfrom起,进程就开始阻塞,即使此使完整的udp数据报还没有到达内核
- 同步/非同步 && 阻塞/非阻塞的概念理解:
- 同步非阻塞模型: “每隔一会儿瞄一眼进度条” 的轮询(polling)方式,数据没准备好时,执行系统调用内核返回一个错误,进程不会阻塞。进程仅在数据准备好之后第2步拷贝数据时阻塞。
- 多路复用IO模型:与同步阻塞模型相比,select函数可以监听多个socket,只要有一个socket数据准备好了,select就会返回,应用进程就可以调用recvfrom处理数据。达到在同一个线程内同时处理多个IO请求的目的。而在同步阻塞模型中,必须通过多线程的方式才能达到这个目的
- 异步非阻塞IO模型:用户进程发起aio_read操作之后,立刻就可以开始去做其它的事,然后,kernel会等待数据准备完成,然后将数据拷贝到用户内存,当这一切都完成之后,kernel会给用户进程发送一个signal或执行一个基于线程的回调函数来完成这次 IO 处理过程,告诉它read操作完成了。
- 区别一 网络模型:redis使用单线程阻塞IO多路复用模型,memchached是多线程非阻塞IO多路复用模型
- 区别二 数据类型:redis支持String(key-value) HashMap ,set,list,zest(sorted-set)五种数据结构,memchached仅支持String一种数据类型。
- 区别三 持久化:redis支持将内存中的数据持久化到硬盘中,memchached全部只在内存中
- 区别四 集群模式:memcached没有原生的集群模式,只能通过一致性哈希算法(???)在客户端实现分布式存储。redis cluster在服务端实现了分布式存储。
如何用redis实现动态点赞
如何设计数据库
点赞、取消点赞是高频次的操作,若每次都读写数据库,大量的操作会影响数据库性能,所以需要做缓存。
redis的hashmap所有数据都存在一个键里,通过这个键方便把所有点赞记录取出。hashmap中的每一项都是一个key-value key为userId::postId(用::把点赞人和被点赞文章隔开,拆开就能得到userId和postId) value为点赞状态(1点赞,0取消点赞)
mysql中也建立点赞表用于持久化存储。被点赞用户id,点赞用户id,点赞状态。再加上主键id,创建时间,修改时间就行了。
开启定时任务(springboot 中用quartz)持久化到数据库
单个redis内存不足时,使用集群进行分片存储
分片就是把大的数据分成几个部分,分开存储。redis利用集群+槽位实现分片。一个redis集群包括16384个槽位(hash slot),数据库中的每个key都对应一个槽位,计算方法为CRC16(KEY)&16384,集群中的每个节点负责处理一部分槽位,如:
- 节点 A 负责处理 0 号至 5500 号哈希槽。
- 节点 B 负责处理 5501 号至 11000 号哈希槽。
- 节点 C 负责处理 11001 号至 16384 号哈希槽。
集群模式下,解耦了key和节点的映射关系。redis节点接收任何与键有关的命令时要先计算键对应的槽,如果槽不在本节点,则通知客户端请求正确的节点,这个过程交moved重定向。多次重定向损耗性能,因此优秀的java客户端会在内部维护槽和节点之间的映射关系,有变化时再借助重定向更新映射关系。集群的伸缩(节点的增减)本质是槽在节点间的移动。比如增加一个节点D,则把节点A,B,C的部分槽移动到D上去。
集群模式下,同时进行大量点赞,如何避免数据不一致?使用分布式锁进行控制
- 加锁在沙滩上踩一脚,留下自己的脚印,就对应了加锁操作。其他进程或者线程,看到沙滩上已经有脚印,证明锁已被别人持有,则等待。
- 解锁把脚印从沙滩上抹去,就是解锁的过程。
- 锁超时为了避免死锁,我们可以设置一阵风,在单位时间后刮起,将脚印自动抹去。
Redis
实现锁的原理在于 SETNX
命令。当 key
不存在时将 key
的值设为 value
,这个value要能标识加锁的线程,返回值为 1
;若给定的 key
已经存在,则 SETNX
不做任何动作,返回值为 0
redis
客户端redisson对分布式锁做了很好的封装
RLock lock = redissonClient.getLock("stockLock");
MongoDB | Es | mysql | |
数据存储形式 | BSON文档(类似ES,JSON),相当于mysql中的一行 所有文档存储在集合中,集合类似mysql的表 | index相当于库,type相当于表,document相当于行,Field相当于列。 mapping定义type下的字段规则,如字段类型,如何分词。 倒排索引: 分布式搜索引擎:索引分拆成多个分片,每个分片可有零个或多个副本。集群中的每个数据节点都可承载一个或多个分片,并且协调和处理各种操作; Master-slave 架构,也实现了数据的分片和备份 | 表 |
查询方式 | MongoDB查询方式 | ||
应用场景 | 模式灵活:数据表不确定,数据属性多样 高可用复制集 可扩展分片集群:集群水平扩展,可存海量数据 索引强大:检索快 | PB级文本的检索和统计分析。
ELK用于故障日志,根据关键字利用倒排索引找到关键错误日志,可视化等 |
用两个条件来查询,比如 where A = a and B = b,如果我用A建立了索引,那么我再用B建立索引会不会提高查询速度?
不一定。当用多个单列索引时索引越多占内存空间越多。合并多个索引结果耗费性能(先用A索引找出符合A=a的结果,再用B索引找出符合B=b的结果,再把结果合并)
最好是对where条件里的列建立联合索引,如何选择索引的列顺序有一个经验法则:将选择性最高的列放到索引最前列。多列索引只能匹配最左前缀,也就是说:
select * from payment where staff_id = 2205 AND customer_id = 93112 ;
select count(*) from payment where customer_id = 93112 ;
可以利用索引,但是 不能利用索引。
select * from payment where staff_id = 2205 ;
数据库索引有哪几种类型
1.普通索引
2.唯一索引,要求索引列的值必须唯一,但允许有空值
3.主键索引,要求索引列是主键,这意味着索引列唯一且不为空
4.组合索引,在多个列上创建索引,只有在查询条件中使用了创建索引时的第一个字段,索引才会被使用。
5.全文索引,类似搜索引擎,根据相关度匹配。
聚集索引和非聚集索引有什么区别
聚集索引的顺序和数据物理存储的顺序一样,类似于按拼音查字典,实际页码就是按照拼音顺序组织的。用B+树描述索引,聚集索引叶节点是数据。非聚集索引是按照数据的某些字段形成的目录,类似于按部首查字典,同一个部首的字在目录中是挨着的,但实际所在的页码并非如此。聚集索引叶节点还是索引,但是包含指向数据的指针,也包含数据的主键。
使用聚集索引查询速度更快,因为直接访问到数据,而且不用二次查询,二次查询指非聚集索引查到的叶节点只有主键和索引字段,如果要其他字段,则要再次去数据行中找。非聚集索引插入速度更快,因为其不必保证物理存储顺序。
聚集索引绝非主键索引,虽然聚集索引默认是主键字段,但给主键用聚集索引往往是一种资源浪费,因为id顺序并无意义,给日期这样的字段更有意义,因为文件经常按日期排序。聚集索引只允许在一个字段上使用,因为不同的两个字段逻辑顺序理论上不可能一致。