Redis


1. 请简要介绍一下Redis是什么?
Redis(Remote Dictionary Server)是一个开源的、基于内存的键值存储数据库。它可以用作数据库、缓存和消息中间件。Redis支持多种数据结构,如字符串、列表、集合、散列表、有序集合等。
2. Redis有哪些优势?
- 读写速度快:基于内存操作,读写速度远高于磁盘数据库。
- 支持多种数据结构:方便解决各种问题。
- 持久化:可以将内存中的数据保存到磁盘中,避免数据丢失。
- 支持事务:可以保证一系列命令的原子性执行。
- 支持主从复制和哨兵机制:实现高可用和分布式。
3. Redis支持哪些数据结构?
Redis支持以下数据结构:
- 字符串(String)
- 列表(List)
- 集合(Set)
- 散列表(Hash)
- 有序集合(ZSet)
4. 请解释一下Redis的持久化机制。
Redis的持久化机制有两种:RDB和AOF。
- RDB(快照):在指定的时间间隔内,将内存中的数据生成快照保存到磁盘上。
- AOF(追加文件):记录每个写操作命令,追加到文件中。在Redis重启时,通过重新执行这些命令来恢复数据。
5. 请介绍一下Redis的事务。
Redis通过MULTI、EXEC、DISCARD和WATCH命令来实现事务功能。事务可以一次性执行多个命令,并保证这些命令的原子性。如果在执行事务过程中出现错误,事务中的所有命令都不会被执行。
6. 请解释一下Redis的主从复制。
Redis的主从复制允许将一个Redis服务器(主节点)的数据复制到一个或多个Redis服务器(从节点)。主节点负责处理写操作,从节点负责处理读操作。主从复制可以实现数据备份、负载均衡等功能。
7. 请介绍一下Redis的哨兵机制。
哨兵(Sentinel)是Redis的高可用解决方案。它负责监控Redis实例的状态,并在主节点发生故障时,自动将一个从节点升级为新的主节点,确保Redis服务的高可用性。
8. 如何解决Redis缓存穿透、缓存击穿和缓存雪崩问题?
- 缓存穿透:可以使用布隆过滤器来过滤掉不存在的键,或者对空结果进行缓存。
- 缓存击穿:可以使用互斥锁或设置热点数据永不过期等方式来解决。
- 缓存雪崩:可以通过设置不同的过期时间、使用分布式缓存和限流等措施来避免。
9. 请谈谈你对Redis集群的理解。
Redis集群是一个分布式数据库,将数据分散存储在多个节点上,从而实现高可用、负载均衡和水平扩展。Redis集群通过分片(Sharding)来管理数据,使用CRC16算法对键进行哈希,将数据映射到不同的节点上。
10. 在使用Redis时,有哪些注意事项?
- 避免大量key同时过期,导致缓存雪崩。
- 合理设置过期时间,避免缓存穿透。
- 使用批量操作和管道技术提高性能。
- 注意内存使用,避免内存泄漏。
- 对敏感数据进行加密处理。

 Redis

(Remote Dictionary Server)是一个开源的、基于内存的数据结构存储系统,可以用作数据库、缓存和消息中间件。它支持多种类型的数据结构,如字符串、哈希、列表、集合、有序集合等,并提供了对这些数据结构的多种操作。

Redis的主要特点包括:

1. **基于内存**:Redis的数据存储在内存中,因此具有极高的读写速度,非常适合需要快速访问的应用场景。

2. **数据持久化**:虽然Redis是基于内存的,但它提供了数据持久化的功能,可以将内存中的数据保存到磁盘中,以防止数据丢失。

3. **支持多种数据结构**:Redis支持多种数据结构,可以满足不同的应用需求。例如,可以使用字符串存储简单的键值对,使用列表实现消息队列,使用哈希存储对象等。

4. **支持事务**:Redis支持事务,允许一次性执行多个命令,并保证这些命令的原子性。

5. **支持复制**:Redis支持主从复制,可以将数据从一个Redis实例复制到另一个Redis实例,实现数据的备份和扩展。

6. **支持高可用和分区**:Redis支持高可用和分区,可以通过哨兵(Sentinel)系统实现自动故障转移,通过Redis集群实现数据的分区存储

7. **支持发布/订阅模式**:Redis支持发布/订阅消息模式,可以实现消息的发布和订阅,用于构建消息系统或实时通信应用

Redis广泛应用于缓存、会话存储、消息队列、排行榜、社交网络等多种场景,是现代应用程序中不可或缺的一部分。由于其高性能和灵活性,Redis成为了许多开发者首选的内存数据库解决方案。

模型结构

1. dictEntry:Redis是Key-Value数据库,因此对每个键值对都会有⼀个dictEntry,⾥⾯存储了指向Key和Value的指针;next指向下⼀个dictEntry,与本Key-Value⽆关。

2. Key:图中右上⻆可⻅,Key(”hello”)并不是直接以字符串存储,⽽是存储在SDS结构中。

  1. redisObject:Value(“world”)既不是直接以字符串存储,也不是像Key⼀样直接存储在SDS中,⽽是存储在redisObject中。实际上,不论Value是5种类型的哪⼀种,都是通过redisObject来存储的;⽽redisObject中的type字段指明了Value对象的类型,ptr字段则指向对象所在的地址。不过可以看出,字符串对象虽然经过了redisObject的包装,但仍然需要通过SDS存储。实际上,redisObject除了type和ptr字段以外,还有其他字段图中没有给出,如⽤于指定对象内部编码的字段;后⾯会详细介绍。

4bit(类型)+4bit(编码)+24bit(lru)+4Byte(refcount)+8Byte(指针)=16Byte

SDS:

//等于 SDS 保存字符串的⻓度 int len;

//记录 buf 数组中未使⽤字节的数量 int free;

//字节数组,⽤于保存字符串 char buf[];

4. jemalloc:⽆论是DictEntry对象,还是redisObject、SDS对象,都需要内存分配器(如

jemalloc)分配内存进⾏存储。

refcount记录的是该对象被引⽤的次数,类型为整型。refcount的作⽤,主要在于对象的引⽤计数和内存回收

                        

数据模型、存储引擎、性能和应用场景

### MySQL

MySQL是一个关系型数据库管理系统,使用SQL(结构化查询语言)进行数据操作。->电子商务网站

- **关系型数据模型**:数据以表格的形式存储,每个表格包含行和列,行代表记录,列代表字段。

- **ACID属性**:确保数据的一致性和完整性。

- **支持事务处理**: - **强大的数据支持**:支持复杂的数据查询和操作。

- **生态**:有丰富的第三方工具和库支持。

### Redis

Redis是一个开源的内存中的数据结构存储系统,可以作为数据库、缓存和消息代理使用。

高性能的缓存场景-->缓存 消息队列   它的主要特点包括:

- **非关系型数据模型**:数据以键值对的形式存储,可以存储字符串、列表、集合、哈希、有序集合等。

- **支持事务处理**:可以确保一系列操作要么全部成功,要么全部失败。

- **数据持久化**:可以将内存中的数据保存到磁盘。

- **高性能**:所有操作都是在内存中执行,因此非常快。

- **社区支持和生态系统**:有丰富的第三方工具和库支持。

### MongoDB

MongoDB是一个开源的文档数据库,支持数据存储、管理和查询。它的主要特点包括:

硬盘存储,mmap映射到内存->社交网络应用 实时数据分析 内容管理系统

- **文档型数据模型**:数据以JSON对象的形式存储,没有固定的表结构。

- **灵活的数据存储**:可以存储复杂的数据结构,包括数组、对象等。

- **支持事务处理**:从MongoDB 3.6开始,部分支持ACID事务

- **查询语言**:使用类似JSON的查询语言,支持丰富的查询操作。

- **社区支持和生态系统**:有丰富的第三方工具和库支持。

### 应用场景

- **MySQL**:适用于需要复杂数据操作和事务处理的应用场景,如传统的关系型应用、电商系统等。

- **Redis**:适用于需要高性能的缓存、消息队列、排行榜、计数器等场景。

- **MongoDB**:适用于需要灵活数据模型和快速查询的应用场景,如实时数据分析、内容管理系统、日志系统等。

而MongoDB适合需要灵活数据模型的场景。。

Redis跳跃表

这种链表加多级索引的结构,就是跳跃表

Redis与mysql数据库缓存一致性如何保证

先删除缓存再更新数据库

更新失败可能导致缓存和数据库的数据是一致的,但仍然是旧的数据

异步重试->如果更新成功可能会导致缓存和数据库数据不一致

我觉得可以通过分布式锁来实现,首先A删除缓存再更新数据库的时候,先建立一个分布式锁,更新数据库成功后释放锁,如果B线程没有读取到缓存,则需要去获取分布式锁,获取到锁之后才能进行读取操作,保证在没有缓存的时候,只能有一个线程操作数据库,从而解决并发操作redis的问题,这种方式的缺点是在锁操作时性能有点影响。

延时双删

1.删除缓存;

2.更新数据库;

3.sleep N毫秒;

4.再次删除缓存。

阻塞一段时间之后,再次删除缓存,就可以把这个过程中缓存中不一致的数据删除掉

读写分离架构

异步更新从库,拿到的数据是旧数据 

此时的解决办法就是如果是对 Redis 进行填充数据的查询数据库操作,那么就强制将其指向主库进⾏查询。

删除失败了怎么办?

如果删除依然失败,则可以增加重试的次数,但是这个次数要有限制,当超出一定的次数时,要采取报错、记日志、发邮件提醒等措施。

如果第二步出现失败的情况,可以采用重试机制解决问题。

更新数据库、再删除缓存

影响更小的方案。先更新数据库,后删除缓存这⼀种情况也会出现问题,

删除失败,那么此时再读取缓存的时候每次都是错误的数据了。采用消息队列补偿

删除成功最终缓存与数据库的数据是一致的,并且都是最新的数据可能B也会读到旧数据

此时解决方案就是利用消息队列进行删除的补偿。具体的业务逻辑⽤语⾔描述如下:

请求 线程A 先对数据库进行更新操作;

在对 Redis 进行删除操作的时候发现报错,删除失败;

此时将Redis 的 key 作为消息体发送到消息队列中;

系统接收到消息队列发送的消息后再次对 Redis 进行删除操作;

但是这个方案会有⼀个缺点就是会对业务代码造成大量的侵入,深深的耦合在⼀起,所以这时会有⼀个优化的方法,我们知道对 Mysql 数据库更新操作后再 binlog 日志中我们都能够找到相应的操作,那么我们可以订阅 Mysql 数据库的 binlog 日志对缓存进行操作

多级缓存

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值