Redis三种常用的缓存读写策略
热衷学习,热衷生活!😄
沉淀、分享、成长,让自己和他人都能有所收获!😄
一、Redis三种常用的缓存读写策略Redis有三种读写策略分别是:旁路缓存模式策略、读写穿透策略、异步缓存写入策略。
这三种缓存读写策略各有优势,不存在最佳,需要我们根据实际的业务场景选择最合适的。
二、旁路缓存模式(Cache Aside Pattern)旁路缓存模式是我们平时使用比较多的一个缓存读写模式,比较适合读请求比较多的场景。
旁路缓存模式中服务端需要同时维护DB和Cache,并且是以DB的结果为准。
读写步骤写:
先更新DB。
然后直接删除cache。
如下图:
读:
从cache中读取数据,读取到就直接返回。
cache中读取不到的话,就从DB读取返回。
再把数据写到cache中。
如下图:
自我思考思考这样子的一个问题:“如果在写数据的过程中,可以先删除cache,再更新DB吗?”
答案:答案肯定是不行的,因为这样子可能造成数据库和缓存数据不一致的问题,比如这个时候有一个数据在DB和缓存都为100,请求1需要将这个数据更新写成200,如果先删除换出再更新数据库的话,在请求1已经删除 ...
Redis知识点&面试题总结
热衷学习,热衷生活!😄
沉淀、分享、成长,让自己和他人都能有所收获!😄
一、简单的介绍一下Redis简单的说Redis就是一个使用C语言开发的一个数据库,不过与传统数据库不同的是Redis的数据是存在内存中的,它是内存数据库,所以读写速度非常快,所以Redis被广泛应用于缓存方向。
另外,Redis除了做缓存之外,也还经常用于做分布式锁,甚至是消息队列。
Redis提供了多种数据类型来支持不同的业务场景。Redis还支持事务、持久化、Lua脚本、多种集群方案。
二、Redis持久化机制Redis是一个支持持久化的内存数据库,通过持久化机制把内存中的数据同步到硬盘文件来保证数据持久化。当Redis重启后通过把硬盘文件重新加载到内存,就能达到恢复数据的目的。
实现:单独创建一个fork()子进程,将当前父线程的数据库文件复制到子进程的内存中,然后由子进程写入到临时文件中,持久化的过程就结束了,再用这个临时文件替换上次的快照文件,然后子进程退出,内存释放。
RDB(Redis DataBase)是Redis默认的持久化方式。按照一定的时间周期策略把内存的数据以快照的形式保存到硬盘的二 ...
InnoDB存储引擎对MVCC的实现
热衷学习,热衷生活!😄
沉淀、分享、成长,让自己和他人都能有所收获!😄
一、一致性非锁定读对于一致性非锁定度的实现,通常的方式是加一个版本号或者时间戳,在更新数据的时候版本号+1或者更新时间戳。查询时,将当前可见的版本号与对应记录的版本号做对比,如果记录的版本号小于可见版本,则表示该记录可见。
在InnoDB存储引擎中,多版本控制就是对一致性非锁定读的实现。如果读取的行正在执行delete或者update操作,这时候读取操作不会去等待行释放锁,而是会去读取行的一个快照数据,对于这种读取历史数据的方式,叫做快照度。
在可重复读和读取已提交两个隔离级别下,如果是执行普通的select语句(不包括select ... lock in share mode, select ... for update)则会使用一致性非锁定读。
并且在可重复读下 MVCC 实现了可重复读和防止部分幻读。
二、锁定读(当前读)如果执行的是下面语句,就是锁定读。
select ... lock in share mode
select ... for update
insert、update、delete ...
MySQL事务隔离级别详解
一、什么是事务?事务是逻辑上的一组操作,要么全执行,要么全不执行。
事务最经典栗子也经常被拿出来的栗子就是银行转账了。比如小明要给小红转账1000元,这个转账会涉及到两个关键操作:将小明的余额减1000元,将小红的余额减1000元。万一这两个操作之间突然出现错误,导致小明余额减少但是小红余额没有增加,这种情况是肯定不允许的。事务就是保证这两个关键操作要么都成功,要么都不成功。
二、事务的特性(ACID)
原子性:事务最小的执行单位,不允许分割。事务的原子性确保动作要么全部执行,要么全部不执行。
一致性:执行事务的前后,数据保持一致。例如转账的业务中,无论事务是否成功,转账者和收款人的总额应该是不变的。
隔离性:并发访问数据库时,一个用户的事务不应该被其他事务所影响,各并发事务之间数据库是独立的。
持久性:一个事务被提交后,它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有影响。
三、并发事务带来的问题在典型的应用程序中,多个事务并发运行,经常会操作相同的数据来完成各自的任务(多个用户对同一数据进行操作)。并发虽然是必须的,但是可能会带来以下的问题:
脏读(Dirty ...
MySQL三大日志(binlog,redo log,undo log)详解
热衷学习,热衷生活!😄
沉淀、分享、成长,让自己和他人都能有所收获!😄
一、MySQL日志MySQL日志主要包括错误日志、查询日志、慢查询日志、事务日志、二进制日志几大类。其中比较重要的就是二进制日志binlog(归档日志)、事务日志redo log(重做日志)和undo log(回滚日志)。
日志关系如下图:
二、redo logredo log(重做日志)是InnoDB存储引擎独有的,它让MySQL有了崩溃恢复的能力。
当MySQL实例挂了或者宕机了,重启的时候InnoDB存储引擎会使用rede log日志恢复数据,保证事务的持久性和完整性。如下图:
MySQL中数据是以页为单数存储,当你查询一条记录时,硬盘会把一整页的数据加载出来,加载出来的数据叫做数据页,会放到Buffer Pool中。后续的查询都是先从Buffer Pool中找,没有找到再去硬盘加载其他的数据页直到命中,这样子可以减少磁盘IO的次数,提高性能。更新数据的时候也是一样,优先去Buffer Pool中找
,如果存在需要更新的数据就直接更新。然后会把“在某个数据页做了什么修改”记录到重做日志缓存(red ...
MySQL索引详解
热衷学习,热衷生活!😄
沉淀、分享、成长,让自己和他人都能有所收获!😄
一、什么是索引?索引有什么作用?索引是一种用于快速查询和检索数据的数据结构。常用的索引数据结构有:B树、B+树、Hash表。
索引的作用就相当于目录的作用。比如:我们在查字典的时候如果没有目录,我们就只能一页一页去查找字,速度很慢,如果有目录,我们只需要查找字所在的页数,然后直接翻到那一页就可以了。
索引的优点缺点优点
索引可以让我们更快的检索出我们需要查找的数据,这也是创建索引的最主要的原因。
可以通过创建唯一索引,保证数据库行数据的唯一性。
缺点
创建索引和维护索引需要耗费更多的时间。当对表中的数据进行增删改时候,如果数据有索引,那么索引也需要动态的修改,会降低SQL执行效率。
索引需要使用物理文件储存,会消耗一定的空间。
但是,使用索引一定能提高查询性能吗?
大多数情况下,索引查询都是比全表扫描的速度要快的,但是如果数据库的数据量不大,那么使用索引不一定能带来很大的提升。
二、索引的底层数据结构常用的索引底层数据结构有三种:B树、B+树、Hash表。
Hash表哈希表就是键值对(key-value ...
Mybatis手撸(二)创建简单的映射器代理工厂
热衷学习,热衷生活!😄
沉淀、分享、成长,让自己和他人都能有所收获!😄
一、前言我们在使用Mybatis的时候,都会有这样子的一个疑问:“为什么Mybatis只需定义一个接口,不用写实现类就能使用XML中或者注解中的SQL语句完成对数据库的CRUD呢?”。看过Mybatis源码之后才知道原来Mybatis使用了Mapper接口代理类,把所有的数据库操作都交给了代理类处理。
二、Binding模块这个Mapper接口代理类在Binding模块,核心类是org.apache.ibatis.binding.MapperProxy。Binding模块核心类如下:
org.apach.ibatis.binding.MapperRegistry:Mapper接口注册类,管理Mapper接口类型和其代理创建工作的映射,我们在开发中创建的Mapper接口类都会注册到这里进行管理。
org.apach.ibatis.binding.MapperProxyFactory:Mapper接口代理类创建工厂类。
org.apach.ibatis.binding.MapperProxy:Mapper接口 ...
Java线程池实现原理详解
热衷学习,热衷生活!😄
沉淀、分享、成长,让自己和他人都能有所收获!😄
一、为什么要使用线程池?线程池提供了一种限制和管理资源(线程、任务)的方式。
这里借用《Java 并发编程的艺术》提到的来说一下使用线程池的好处:
降低资源消耗:通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
提高响应速度:当任务到达时,任务可以不需要等待创建线程就能立即执行。
提高线程的可管理性:线程是稀缺资源,如果无线的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。
二、ThreadPoolExecutor类分析Java线程池主要由Executor框架实现,Executor 框架不仅包括了线程池的管理,还提供了线程工厂、队列以及拒绝策略等,Executor 框架让并发编程变得更加简单。
线程池实现类ThreadPoolExecutor是Executor框架最核心的类,我们就从这个类的学习线程池的实现原理。
核心属性12345678910111213141516171819202122232425262728293031323334353637383 ...
Thread状态流转、方法使用、原理分析
热衷学习,热衷生活!😄
沉淀、分享、成长,让自己和他人都能有所收获!😄
一、Thread状态Java的线程状态描述在Thread类里面的枚举类State中,包路径为java.lang.Thread.State,总共包含以下六种状态:NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED
123456789101112131415161718192021222324252627282930public enum State { // 尚未启动的线程的线程状态 NEW, // 可运行线程的线程状态,是可运行的线程 // 这个状态在Java虚拟机中进行,但它可能等待来自操作系统的其他资源,比如处理器 RUNNABLE, // 线程阻塞等待监视器锁的线程状态 // 处于阻塞状态的线程正在等待监视器锁 // 例如synchronized锁 BLOCKED, // 等待线程的线程状态 // 线程调用以下方法会处于等待状态:Object.wa ...
Mybatis手撸(一)Mybatis简介和整体架构
热衷学习,热衷生活!😄
沉淀、分享、成长,让自己和他人都能有所收获!😄
一、Mybatis简介MyBatis 官方文档
Mybatis是一款旨在帮助开发人员屏蔽底层重复性的JDBC代码的持久层框架,支持通过配置文件或者注解将ResultSet映射成Java对象。相对于其它ORM框架,Mybatis更为轻量级,支持定制化SQL和动态SQL,方便优化查询性能,同时包含了良好的缓存机制。
二、Mybatis整体架构Mybatis整体架构如下图:
接口层
SqlSession接口层定义了暴露给应用程序调用的API,接口层在收到请求时会调用核心处理层的相关模块完成具体的数据库操作。
核心处理层
配置解析:Mybatis初始化时会加载配置文件、映射文件和Mapper接口的注解信息,解析完毕后会已对象的形式保存到Configuration对象中。
SQL解析与scripting 模块:Mybatis支持通过配置实现动态的SQL,即根据不同参数生成SQL。
SQL执行与结果集映射:Executor负责维护缓存和事务管理,并将数据库操作委托给StatementHandler,Parmater ...