MySQL锁等级
MySQL锁的类型数据库锁的类型主要有: 表锁 行锁 间隙锁 临键锁 知识点助记把数据库比作图书馆,看书就是读数据,借还书就是写数据 表锁:就像图书馆闭馆清点。谁也不准进来,谁也不让出去。优点是管理简单,缺点是效率低。 行锁:就像读者用个人借书卡锁定了某本具体的书。其他人可以随便看,借还别的书,但是被锁定的这本书,在被归还(事务结束)前别人不能借走(修改)。 间隙锁:图书馆的书架不是连续的,有些书架上是空着的。间隙锁就是锁住这些空位置,禁止任何人往这个空位里插入新书。但是他不锁任何现有的书 临键锁:这其实就是行锁+间隙锁的组合技。他不但要锁住你想要的那本书,还要锁住他旁边的空位。这是在InnoDB在默认隔离级别(可重复读)下防止幻读的手段。 具体实现 表锁:就是锁住整张表,实现简单,开销小。 LOCK TABLES table_name READ; -- 加读锁(共享锁),别人可读不可写LOCK TABLES table_name WRITE; -- 加写锁(排他锁),别人既不可读也不可写-- ... 你的操作 ...UNLOCK TABLES; -- 释放锁 行锁...
MySQL的事务隔离等级
MySQL的事务隔离等级知识点助记 读未提交(RU):就像在喧闹的开放式讨论区。你可以看到别人正在纸上涂改,甚至还没定稿的笔记,草稿。效率高,但容易读到错误信息 读已提交(RC):在普通的阅览区,你只能看见别人正式上架的(提交)的书籍。但是在你这次阅读和下次阅读之间,书架上的书可能被人换走了 可重复读(RR):像在一个私人阅览室,你进去的时候,管理员会为你需要的所有书拍一张快照。在你离开前,你每次看到的内容都是这个快照里的内容,其他读者无法换走你正在看的书。但是可能有新书入库,你的快照里没有。 串行化(SI):图书馆一次只能允许一位读者进入,绝对安静。 读未提交事务可以读取其他事务尚未提交的数据修改性能最高,基本上无锁开销,但正确率最低。会造成:脏读。你可能读到另一个事务中途修改,随后又回滚的无效数据(脏数据) 读已提交一个事务只能读取到其他事务已经提交的数据修改,避免了脏读。但会造成不可重复读。同一个事务内,两次执行相同的查询,可能会得到不一样的结果(因为其他食物在这中间提交了修改)。 可重复读保证在同一事务中,多次读取同一范围的数据时,看到的结果是一致的。是MySQL的默认...
Redis的数据一致性
Redis的数据一致性背景我们的数据一般都会持久化到数据库,但是数据库操作很慢Redis处理速度快,但是数据不一定是最新的简单来说就是:数据库里的数据如果改了,Redis里面存的可能还是旧数据这就导致了一个问题:当多线程访问系统时,如何能保证数据库和Redis的数据同步、一致呢 分析关于双写一致性问题有两种解决思路。 更新缓存 删除缓存 更新缓存 如果我们先更新库,再更新缓存 假设有两个请求,都对同一条数据进行操作A要把这条数据改为100 B要把这条数据改为200 首先请求A先把数据库中的数据改为100,刚更新完库还没来得及更新缓存,B就来把数据改为200,然后B立刻把200写入缓存,此时A再去更新缓存为100此时缓存是100 数据库是200 如果我们先更新缓存,再更新库 前置条件同上 首先请求A先把缓存中的数据改为100,还没来得及更新数据库,B来把缓存改为200,并把数据库改为200。此时A才来更新数据库为100此时缓存是200 数据库是100 删除缓存此时我们考虑读写并发的场景下会有什么问题请求A是读操作,B是写操作,要改为200初始:缓存和数据库中数据都是100...
关于双亲委派机制
双亲委派机制知识点助记比如你是一个小孩(子类加载器),你想要买一本新书(加载一个类)。你不会直接去书店自己买,而是先问爸妈(父类加载器)家里有没有这本书如果爸妈说有,就直接用家里的;如果没有,你猜自己掏钱去买。 这保证了: 层次性:爷爷奶奶->爸爸妈妈->你 形成一个责任链 委托优先:永远让长辈解决,避免重复加载类 安全底线:防止乱买书(比如恶意代码替换核心类) 解析其实双亲委派机制是Java类加载器的工作规则:当一个类加载器收到加载类的请求时,他不会自己加载,而是递归的委托给父类加载器去尝试,只有父类加载器都失败时,他才亲自出马 Java中有三类核心类加载器 BootStrap ClassLoader(爷爷辈):C++实现,加载JRE/lib下的核心库,比如java.lang.* Extension ClassLoader(父辈):加载JRE/lib/ext下的扩展库 Application ClassLoader(子辈):加载用户类路径(ClassPath)的类 好处 避免类重复加载:如果每个加载器都自己干,同一类可能被加载多...
深入理解Java AQS 原理
深入理解JavaAQS原理知识点助记可以把AQS想象成一个“交通指挥系统” 红绿灯 = AQS的状态管理(state变量) 等待的车流 = 堵塞的线程队列 交警的指挥 = AQS的排队和唤醒机制 不同车道 = 独占模式 和 共享模式 其核心价值在于:用统一的规则管理谁可以通过(获取锁),谁需要等待以及什么时候放行。 解析AQS 是 AbstractQueuedSynchronizer 的简称,它是 JDK1.5 引入的一个抽象类,提供了基于FIFO等待队列的线程同步机制。 // 1. 状态管理 - 红绿灯状态private volatile int state;// 2. 等待队列 - 排队的车辆private transient volatile Node head;private transient volatile Node tail;// 3. 节点类型 - 不同的等待模式static final class Node { // 共享模式、独占模式、条件等待等} 好处在AQS出现之前,每个同步工具都要...
关于Redis的数据持久化
关于Redis的数据持久化背景因为Redis是基于缓存存储数据,一旦服务重启或者崩溃,数据就全部会丢失。 主要措施 RDB(快照):就像给一个场景拍一张照片。每隔一段时间或者到达某种状态时,就会把全部数据生成一个快照文件,存储在磁盘中。恢复时直接拿出最新照片复原即可。 AOF(日志):就像给一个场景拍视频。每次操作都会记录下来,比如你操作了某个数据,就会记录下来,然后生成一个日志文件,存储在磁盘中。恢复时不需要回忆最终的状态,只需要把视频做过的事情重新做一遍就可以了。 简单来说。RDB是某个状态的备份,而AOF是操作历史的备份。 关于RDB是什么在特定时间点,将Redis内存中所有的数据生成一个二进制压缩文件(默认dump.edb)。 优点 恢复速度快:服务器宕机后,能用RDB文件快速恢复数据 性能高:生成的RDB文件是子进程完成的,几乎不阻塞主进程的执行 适合备份:紧凑的二进制文件,便于传输和备份 如何配置在redis.conf中,主要配置save指令,定义快照的触发条件 # 格式:save <秒> <写操作次数>save 900 1 # 90...
关于Redis的击穿穿透与雪崩
关于Redis的击穿穿透与雪崩知识点助记就比如你开了一个商店,Redis就像放在门外面的小货架,那上面摆放着最畅销的商品。 但是有这么三种情况会造成商店崩溃: 缓存击穿:有一个很热门的商品正好过期了,这个时候涌入了一大批购买这个商品的顾客,所有人都涌向了你的小商店去买这一个物品,造成系统瘫痪。 缓存穿透:有一个调皮的小孩子,他一直管你要你商店里没有的东西,这导致店员每次都要去找这个不存在的商品。大量这样的请求会让店员累坏。 缓存雪崩:货架上很多畅销的产品在同一时间过期,这个时候来了很多顾客来买这些商品,导致大量请求瞬间砸向商店,造成系统瘫痪。 解决办法缓存击穿核心思路就是防止多个请求同时去数据库查询同一个失效的热点key 对于极热点key设置永不过期。通过后台任务或者消息队列在数据更新时主动刷新缓存。 互斥锁:当第一个请求发现缓存失效时,他并不直接去查数据库,而是先获取一个分布式锁。获取锁成功的请求才有资格去查询数据表并重建缓存。其他请求则等待,缓存重建完后直接从Redis中获取数据。 // 以下是伪代码public String getData(String key)&...
关于电商平台如何遍历所有下级的实现
关于电商平台如何遍历所有下级的实现背景电商平台邀请人和被邀请人是有层级关系的,比如A邀请B,B邀请C,C邀请D,C又邀请了E。那么A的下级就是B、C、D、E在很多场景下,邀请人都可以通过下级获取利益,分红。那么我们该如何获取A的所有下级呢? 实现如果我们是用一个人去找他的所有的上级。那我们可以直接递归实现。比如先获取这个用户的邀请人,再不断地向上寻找,直到找到没有上级的那个邀请人(根)为止。 但是如果是一个人去寻找他的所有下级。那大概率就是一个树形结构。而且是无限层级的树。我们如果用递归的话会对性能造成很大的消耗,并且极有可能造成栈溢出。 我们可以换一种办法。 用人口普查的例子来说。就是一个登记员先拿走这个人的名字,并登陆他的信息,然后问这个人:你的儿子**(直接下级)是谁?然后把闻出来的所有的儿子的名字都记录下来(假设B、C),依次写在待等级名单的末尾。登记员再从名单的最前面打走下个名字(B),然后继续问:你的儿子(直接下级)**是谁?然后把B的直接下级(D、E)写在名单末尾。就这样以此类推,直到名单空为止。 好处好处在于我们是使用队列实现该功能,而队列存储在堆内存中,空间很大...
RedisTemplate的使用
RedisTemplate的使用RedisTemplate是Spring Data Redis提供的核心抽象类,是Spring Boot访问Redis服务器的底层实现。 有了RedisTemplate就不用Jedis的连接池或者直连,手动序列化对象,查询时还需要手动反序列化,还要处理各种异常和链接关闭 RedisTemplate就可以直接访问Redis服务,并且自动处理各种异常和链接关闭 redisTemplate.opsForValue().set("user:1", user);User result = (User) redisTemplate.opsForValue().get("user:1"); 核心配置RedisTemplate使用之前需要配置RedisConnectionFactory @Configurationpublic class RedisConfig { @Bean public RedisTemplate<String, Object> redisTemplate( ...
Redis用ZSet实现实时积分排行榜
Redis用ZSet实现实时积分排行榜背景需求:实时积分排行榜要求实时性,有序性 为什么要用Redis的ZSetRedis的ZSet就像一个巨型的的电子记分牌,上面会有所有用户的积分和排名情况ZSet是由Redis提供的一种数据结构。他存储一组唯一的成员,每个成员关联一个分数。成员按分数自动排序。 极致的实时性 天然排序 简单易用 高性能、高并发 而使用数据库(如MySQL),一是实时性低,二是复杂度高,需要写sql,最后就是高并发能力差。 核心操作 ZADD key score member : 添加或更新成员及其分数 ZINCRBY key increment member : 给指定成员分数增加(可正可负)分数。(最常用) ZREVRANGE key start stop : 获取分数从高到底(REV是reverse)排名在[start,stop]区间内的成员 ZREVRANK key member : 获取指定成员在从高到低排名中的名次(0表示第一名) ZSCORE key member : 获取指定成员的分数 ZCARD key : 获取ZSet的成员数量 具体实...
