Redis内存策略
Redis内存策略
过期策略
在使用Redis缓存的时候,我们可以通过expire命令给Redis的key设置TTL(存活时间) 当TTL过期之后会对key进行删除,从而起到内存回收的目的。 但是有没有想过底层是怎么做到的,有两个问题?? 1. Redis怎么知道一个key过期了 2. 是不是TTL过期之后就立马删除了
第一个问题 Redis通过一个dict来存储相应key的对应过期时间。在Redis的存储结构中,有两个Dict:一个用来记录key-value;另一个用来记录key-TTL。
第二个问题 并不是立马进行删除的,是通过一定的规则进行删除的: 比如惰性删除和周期删除
惰性删除 惰性删除:顾名思义并不是在TTL到期后就立刻删除,而是在访问一个key的时候,检查该key的存活时间,如果已经过期才执行删除。
周期删除 周期性的抽样部分过期的key,然后执行删除。有快和慢两种模式: ● SLOW模式是通过定时任务以固定频率(默认每秒10次)执行过期key的清理,每个执行周期不超过25ms。此模式会逐个检查数据库中的bucket,并抽样20个key检查是否过期,如果过期key的比例 ...
Redis网络模型
Redis网络模型
阻塞IO
应用程序想要去读取磁盘中的某个数据。 用户去读取数据时,会去先发起recvform一个命令,去尝试从内核上加载数据,如果内核没有数据,那么用户就会等待,此时内核会去从硬件上读取数据,内核读取数据之后,会把数据拷贝到用户态,并且返回ok,整个过程,都是阻塞等待的,这就是阻塞IO
非阻塞IO
非阻塞IO的recvfrom操作会立即返回结果而不是阻塞用户进程。 可以看到,非阻塞IO模型中,用户进程在第一个阶段是非阻塞,第二个阶段是阻塞状态。 虽然是非阻塞,但性能并没有得到提高。而且忙等机制会导致CPU空转,也就是忙等。
IO多路复用
IO多路复用是利用单个线程来同时监听多个FD(文件),并在某个FD可读、可写时得到通知,从而避免无效的等待,充分利用CPU资源。不过监听FD的方式、通知的方式又有多种实现,常见的有: ● select ● poll ● epoll
其中select和pool相当于是当被监听的数据(FD)准备好之后,但是你不确定这个是哪个FD准备好了,它只告诉你有FD好了,你需要到整个FD中去找,但是你现在并不知道这个FD是谁的,所以你需要 ...
Redis数据结构原理
Redis数据结构原理
String
String有三种编码方式: 1.RAW编码:基于简单动态字符串实现 2.EMBSTR编码 3.INT编码
RAW,基于简单动态字符串(SDS)实现,存储上限为512mb。
如果存储的SDS长度小于44字节(RedisObject+SDS的长度加起来刚好是64,这样做的好处是不会产生内存碎片),则会采用EMBSTR编码,此时RedisObject与SDS是一段连续空间。申请内存时只需要调用一次内存分配函数(RAW编码需要调用两次内存分配函数,先申请RedisObject再申请SDS的)
如果存储的字符串是整数值,并且大小在LONG_MAX(8字节)范围内,则会采用INT编码:直接将数据保存在RedisObject的ptr指针位置(刚好8字节),不再需要SDS的参与了
long型还有的特点是: 在对string进行incr(+1), decr(-1)等操作的时候 ● 如果它内部是OBJ_ENCODING_INT编码,那么可以直接行加减操作; ● 如果它内部是OBJ_ENCODING_RAW或OBJ_ENCODING_EMBSTR编码,那么Redis ...
Redis自己创建的数据类型
Redis自己创建的数据类型
SDS
简单动态字符串SDS
C里面一般用字符数组来实现字符串,字符数组是有一些问题的: 1.非二进制安全(也就是说不能包含’\0’,但是可能会有需求在字符串中假如\0这个字符) 2.不可以修改(有些时候我们需要对key进行append操作什么的,所以需要修改字符串) 由于C语言字符数组来实现字符串有问题,Redis用着不方便,所以Redis就自己造了个字符串类。
Redis会根据字符串的长度进行选择合适的SDS结构体,比如字符串长度小于255,我就给你分配一个可以刚好容纳的下的SDS结构体,所以有不同规格的SDS结构体,可以容纳不同大小的字符串。这样的话是不是就可以节约内存啦
SDS之所以叫做动态字符串,是因为它具备动态扩容的能力,例如一个内容为“hi”的SDS结构体
现在要给这个hi后面追加一段字符串“,Amy”,这里首先会申请新内存空间: ● 如果新字符串小于1M,则新空间的大小为 扩展后字符串长度的两倍+1; ● 如果新字符串大于1M,则新空间的大小为 扩展后字符串长度+1M+1。 需要注意的是,下面的新空间的大小是13,但是alloc只显示去掉 ...
Redis持久化原理
Redis持久化
Redis有两种持久化方案: ● RDB持久化 ● AOF持久化
RDB被叫做Redis数据快照。简单来说就是把内存中的所有数据都记录到磁盘中。当Redis实例故障重启后,从磁盘读取快照文件,恢复数据。快照文件称为RDB文件,默认是保存在当前运行目录。
RDB持久化在四种情况下会执行: 
● 执行save命令(save命令会导致主进程执行RDB,这个过程中其它所有命令都会被阻塞)
● 执行bgsave命令(这个命令执行后会开启独立进程完成RDB,主进程可以持续处理用户请求,不受影响。) 
● Redis停机时(会默认保存数据,进行持久化) 
● 触发RDB条件时(比如900秒内,如果至少有1个key被修改,则执行bgsave)
bgsave原理: bgsave开始时会fork主进程得到子进程(注意这里都是进程,而不是线程),子进程通过主进程复制过来的页表共享主进程的内存数据。然后把主进程的数据进行备份到磁盘。
fork采用的是copy-on-write技术: 
● 当主进程执行读操作时,访问共享内存(这里面的内存数据是只读的); 
● 当主进程执行写操作时,则会对这 ...
12306
简历上描述**项目名称:**12306铁路购票系统**项目描述:**12306 铁路购票系统,帮助用户完成互联网在线购票,提高居民买票效率以及减少售票人员工作。项目基础架构采用 JDK17、SpringBoot3 和SpringCloud Alibaba 构建,完成会员注册、车票查询、车票下单以及支付等业务。底层采用缓存、消息队列以及分库分表等技术支持海量用户购票以及数据存储。**核心技术: **SpringBoot + SpringCloudAlibaba + RocketMQ + ShardingSphere + Redis + MySQL+ Sentine+ Hippo4j功能描述:
使用责任链模式重构请求数据准确性检验,比如:查询购票、购买车票下单以及支付结果回调等业务。
通过 RocketMQ 延时消息特性,完成用户购票 10 分钟后未支付情况下取消订单功能。
封装缓存组件库避免注册用户时,用户名全局唯一带来的缓存穿透问题,减轻数据库访问压力。
通过引入路由表解决查询用户信息时不带分片键将会触发的读扩散问题。完成通过不同的登陆方式进行登录的功能。
通过开发防重复提交注解,实 ...
JUC中的原子类
JUC中的原子类原子整数 J.U.C 并发包提供了: 
AtomicBoolean 
AtomicInteger 
AtomicLong
以 AtomicInteger 为例  
AtomicInteger i = new AtomicInteger(0);// 获取并自增(i = 0, 结果 i = 1, 返回 0),类似于 i++System.out.println(i.getAndIncrement());// 自增并获取(i = 1, 结果 i = 2, 返回 2),类似于 ++iSystem.out.println(i.incrementAndGet());// 自减并获取(i = 2, 结果 i = 1, 返回 1),类似于 --iSystem.out.println(i.decrementAndGet());// 获取并自减(i = 1, 结果 i = 0, 返回 1),类似于 i--System.out.println(i.getAndDecrement());// 获取并加值(i = 0, 结果 i = 5, 返回 0)System.out.println(i.g ...
深入理解ReentrantLock
深入理解ReentrantLock相对于 synchronized 它具备如下特点  
可中断                                                    相关方法:lock.lockInterruptibly()
可以设置超时时间                                   相关方法:lock.tryLock(1, TimeUnit.SECONDS)
可以设置为公平锁(防止线程饥饿)             相关方法:new ReentrantLock(true)
支持多个条件变量                                    相关方法:lock.newCondition()
 此外,和synchronized一样,都支持可重入  
 基本语法  
注意:要保证lock和unlock成对出现
// 获取锁reentrantLock.lock();try {    // 临界区} finally {    // 释放锁    reentrantLock.unloc ...
线程八锁
其实就是考察 synchronized 锁住的是哪个对象  
 情况1:12 或 21  
@Slf4j(topic = "c.Number")class Number{    public synchronized void a() {        log.debug("1");    }    public synchronized void b() {        log.debug("2");    }}public static void main(String[] args) {    Number n1 = new Number();    new Thread(()->{ n1.a(); }).start();    new Thread(()->{ n1.b(); }).start();}
 情况2:1s后12,或 2 1s后 1  
@Slf4j(topic = &quo ...
Java集合详解
集合导学这次课程主要涉及到的是List和Map相关的面试题,比较高频就是
ArrayList
LinkedList
HashMap
ConcurrentHashMap
ArrayList底层实现是数组
LinkedList底层实现是双向链表
HashMap的底层实现使用了众多数据结构,包含了数组、链表、散列表、红黑树等
在讲解这些集合之后,我们会讲解数据结构,知道了数据结构的特点之后,熟悉集合就更加简单了。在讲解数据结构之前,我们也会简单普及一下算法复杂度分析,让大家能够评判代码的好坏,也能更加深入去理解数据结构和集合。
1 算法复杂度分析1.1 为什么要进行复杂度分析?我们先来看下面这个代码,你能评判这个代码的好坏吗?
/** ** *求**1~n**的累加和 ** @param* *n ** @return*/public int sum(int n) {    int sum = 0;    for ( int i = 1; i <= n; i++) {        sum = sum + i;    }    return sum ...

