一、redis的5种数据类型
1、string-----------------字符串类型
2、hash------------------散列类型
3、list---------------------列表类型
4、set--------------------无序集合类型
5、zset-------------------有序集合类型
不同数据类型的读写
- string
- set key value
- get key
- hash
- hset key 字段 值
- hget key 字段
- list
- lpush 键 aa bb cc
- rpush 键 aa bb cc
- lrange 键 0 -1
- set
- sadd 键 aaa bbb ccc
- smembers 键
- spop 键
- zset
- zadd 键 分数 值1 分数 值2
- zrange 键 0 -1
- zrange 键 0 -1 withscores
- zrevrange 键 0 -1 withscores
二、redis是单线程吗?
是的,Redis是单线程的。Redis采用了事件驱动模型,使用一个主线程来处理网络请求、读写数据和执行命令。这种设计使得Redis能够充分利用操作系统提供的I/O多路复用机制,高效处理大量的并发连接。虽然Redis是单线程的, 但是通过单线程透明的访问操作系统,从而实现并发处理大量的连接和请求。
三、redis6为何引入多线程?
Redis6引入多线程主要是为了提高系统的并发处理能力和性能。在之前的版本中,Redis是单线程的架构,每个连接都是在单个线程上处理的,这限制了系统的并发能力。
而在Redis6中引入了多线程模型,可以同时处理多个连接和操作,从而提高了并发处理的能力。多线程模型允许Redis同时处理多个请求,减少了请求排队的情况,大大提高了系统的吞吐量。
此外,多线程模型还可以充分利用多核处理器的计算能力,通过并行处理来提高系统的性能。在处理大量连接和高并发的场景下,多线程模型可以更有效地利用系统资源,提供更好的性能和响应时间。
四、redis的持久化策略
Redis有两种持久化策略:RDB(Redis DataBase)和AOF(Append-Only File)。
RDB持久化:RDB持久化是通过定期将Redis的数据集快照存储到硬盘上,实现数据的持久化。它是通过fork一个子进程来将当前内存中的数据写入一个临时文件,然后再把这个临时文件替换掉之前的RDB文件,以达到更新数据的目的。RDB有两种触发方式:一种是定时触发,可以通过设置save参数来控制间隔时间;另一种是在一定时间内发生了一定数量的写操作时触发。RDB的优点是产生的文件相对较小,恢复数据的速度也较快,但是存在数据丢失的风险。
AOF持久化:AOF持久化是通过将Redis的写操作追加到一个文件(AOF文件)中,实现数据的持久化。当Redis重启时,会重新执行AOF文件中的写操作来恢复数据。AOF持久化有三种策略:每秒钟同步一次、每写入一次操作都同步一次和从不同步。其中,每秒钟同步一次是默认的策略,可以通过设置appendfsync参数来改变策略。AOF的优点是数据的安全性更高,可以避免数据丢失的风险,但是文件相对较大,恢复数据的速度相对较慢。
- 混合持久化(AOF + RDB): 这种方式结合了 AOF 和 RDB 的优点,既能保证数据的完整性和持久性,又能获得较高的性能。在这种模式下,Redis 会先使用 AOF 持久化来保证数据的完整性,然后定期使用 RDB 持久化来生成快照文件,以提高恢复速度和降低文件大小。
在实际应用中,可以根据数据的重要性和对数据的要求来选择合适的持久化策略,也可以同时使用RDB和AOF来提高数据的安全性和恢复速度。
rdb方式与aof方式的区别?
rdb是采用快照的方式定时存储,它比较节省资源,但可能会导致未保存的数据意外丢失 aof是采用日志的方式即时存储,它消耗的资源会比rdb方式更多,但它可以防止数据意外丢失
五、缓存击穿、缓存雪崩、缓存穿透
1、缓存击穿
原理:
如果缓存中某个热点数据过期了,此时大量请求访问该热点数据,就无法从缓存中读取,直接访问数据库,数据库很容易被高并发的请求冲垮。
解决方案:
1、互斥锁方案,保证同一时间只有一个业务线程更新缓存,未能获取互斥锁的请求,要么等待锁释放后重新 读取缓存,要么就返回空值或者默认值。
2、不给热点数据设置过期时间,由后台异步更新缓存,或者在热点数据准备要过期前,提前通知后台线程更 新缓存以及重新设置过期时间;
2、缓存雪崩
原理:
当大量缓存数据在同一时间过期(失效)或者 Redis 故障宕机时,如果此时有大量的用户请 求,都无法在 Redis 中处理,于是全部请求都直接访问数据库,从而导致数据库的压力骤增,严重的会造成 数据库宕机,从而形成一系列连锁反应,造成整个系统崩溃,这就是缓存雪崩的问题。
解决方案:
- 均匀设置过期时间;
- 互斥锁;
- 双 key 策略;
- 后台更新缓存;
3、缓存穿透
原理:
当用户访问的数据,既不在缓存中,也不在数据库中,导致请求在访问缓存时,发现缓存缺失,再去访问数据库时,发现数据库中也没有要访问的数据,没办法构建缓存数据,来服务后续的请求。那么当有大量这样的请求到来时,数据库的压力骤增,这就是缓存穿透的问题。
解决方案:
- 非法请求的限制;
- 缓存空值或者默认值;
- 使用布隆过滤器快速判断数据是否存在,避免通过查询数据库来判断数据是否存在;
六、redis实现分布式锁
6.1、什么是分布式锁
分布式锁是一种机制,用于确保在分布式系统中,多个节点在同一时刻只能有一个节点对共享资源进行操作。它是解决分布式环境下并发控制和数据一致性问题的关键技术之一。
分布式锁的特征:
- 互斥性:任意时刻,只有一个客户端能持有锁。
- 锁超时释放:持有锁超时,可以释放,防止不必要的资源浪费,也可以防止死锁。
- 可重入性:一个线程如果获取了锁之后,可以再次对其请求加锁。
- 高性能和高可用:加锁和解锁需要开销尽可能低,同时也要保证高可用,避免分布式锁失效。
- 安全性:锁只能被持有的客户端删除,不能被其他客户端删除
6.2、redis实现分布式锁的7中方案
- SETNX + EXPIRE
- SETNX + value 值(系统时间 + 过期时间)
- 使用 Lua 脚本(包含 SETNX + EXPIPE 两条指令)
- SET 的扩展命令(SET EX PX NX)
- SET EX PX NX + 校验唯一随机值,再删除
- Redisson框架
- 多机实现的分布式锁Redlock+Redisson
参考及详解:
Redis实现分布式锁的7种方案,及正确使用姿势!
七、Redis是如何解决Hash冲突的?
redis是通过我们的链式hash来解决我们的hash冲突问题,哈希算法产生的哈希值的长度是固定并且是有限的,比如说我们通过MD5算法生成32位的散列值,那么它能生成出来的长度则是有限的,我们的数据如果大于32位是不是就可能存在不同数据生成同一个散列值,那么redis通过链式hash,以不扩容的前提下把有相同值的数据链接起来,但是如果链表变得很长就会导致性能下降,那么redis就采用了rehash的机制来解决,类似于hashmap里面的扩容机制,但是redis中的rehash并不是一次把hash表中的数据映射到另外一张表,而是通过了一种渐进式的方式来处理,将rehash分散到多次请求过程中,避免阻塞耗时。
八、redis如何保证与数据库的双写一致性
事务性操作: 在将数据写入 Redis 之前,首先确保将数据写入主数据库。然后,使用 Redis 的事务性操作将数据写入 Redis。这样可以确保在 Redis 中的数据更新操作与主数据库的写入操作是原子性的。
使用消息队列: 可以通过在主数据库写入操作后将消息发送到消息队列,然后由消费者从消息队列中获取消息并将数据写入 Redis,从而实现主数据库和 Redis 的异步更新。这样可以将主数据库的写入操作与 Redis 的更新解耦,提高了系统的并发性和可扩展性。
定期同步: 定期从主数据库中同步数据到 Redis,确保 Redis 中的数据与主数据库保持一致。可以使用定时任务或者数据库的触发器来实现定期同步。
使用双写模式: 在应用层同时操作主数据库和 Redis,确保数据同时写入两者。这种方式需要确保写入操作的原子性,以防止出现数据不一致的情况。
九、redis是如何处理过期的数据的?
Redis 使用一种称为惰性删除(lazy expiration)的方式来处理过期数据。这意味着 Redis 并不是立即在键过期时将其删除,而是在某个键被访问时检查它是否过期,如果过期了,才会将其删除。
具体来说,当客户端尝试访问一个键时,Redis 会首先检查该键是否设置了过期时间。如果设置了过期时间,Redis 会在访问该键时检查它是否过期,如果过期了,则会在访问前删除该键并返回空值,否则会返回键对应的值。
在处理过期键时,Redis 使用定期删除(定时任务)和惰性删除相结合的策略:1.定期删除: Redis 会周期性地(默认每秒钟检查10次)随机抽取一些设置了过期时间的键,并检查它们是否过期,如果过期则删除。这样可以确保过期的键会在一定时间内被及时清理。
2.惰性删除: 当客户端尝试访问一个键时,Redis 会在访问前检查该键是否过期,如果过期则会被删除。这样可以避免定期删除带来的性能开销,并且可以在键被访问时立即删除过期键,释放内存空间。
十、redis为什么快
1.内存存储:Redis将数据存储在内存中,实现了快速的读写操作。
2.单线程模型: Redis采用单线程处理请求,避免了多线程的竞争和上下文切换开销。
3.高效的数据结构:Redis内部使用了高效的数据结构,如哈希表、跳跃表等,提供了快速的数据访问和操作。
4.异步l0: Redis利用异步IO来处理网络请求,能够同时处理多个请求,提高并发性能。
5.事件驱动架构:Redis基于事件驱动的模型,通过事件循环机制处理请求和操作,提高系统的效率。
6.优化的操作:Redis对常用操作进行了优化,如批量操作和管道技术,减少了网络通信开销。
十一、redis集群
11.1、原理
Redis集群的原理主要包括分片和复制两个方面。
分片(Sharding):Redis集群使用分片来将数据分布在多个节点上。每个节点负责存储和处理一部分数据。分片有两种方式:
- 哈希分片(Hash Sharding):通过使用哈希算法将键分配到不同的节点上。通常使用CRC16算法计算键的哈希值,然后将哈希值对节点数量取模,确定键应该存储在哪个节点上。
- 范围分片(Range Sharding):将所有键按照一定的范围划分,并将每个范围分配给不同的节点。每个节点负责一个或多个范围的键。
复制(Replication):为了提高可用性和容错性,Redis集群还使用了复制机制。每个节点都可以有若干个从节点(Slave),从节点负责复制主节点(Master)上的数据。主节点和从节点之间通过异步复制进行数据同步,主节点将写操作记录在AOF或RDB文件中,并将这些操作发送给从节点进行执行。从节点会定期向主节点发送心跳请求,以检查主节点是否可用。当主节点不可用时,从节点会选举出一个新的主节点继续提供服务。
Redis集群还包括一些其他的机制来确保数据的可用性和一致性,比如故障检测和故障恢复机制。当节点发生故障时,集群会自动检测故障节点,并进行故障转移,将数据重新分配到其他正常节点上。同时,Redis集群还支持客户端的自动重定向,当客户端请求到达错误的节点时,节点会自动将请求重定向到正确的节点上。
11.2、配置redis集群的要求
1、redis的主机数量必须是单数,至少需要配置3台redis主机
2、redis的主机需要配置从机。配置redis集群至少需要6台redis服务器,其中3台主机,3台从机
11.3、判断redis集群是否失败的标准
1、如果集群中主机挂了,它如果没有配置从机。该节点无法访问,集群失败无法使用
2、如果集群中有一半以上的主机挂了,即使它们配置了从机,集群也是失败的
11.4、redis集群存储数据
当配置redis集群中,集群中会产生16384个哈希槽(哈希槽用于具体存储数据),这些哈希槽会均分到 每一台主机上,当向redis集群存储数据时,redis存放数据是采用:键值对方式存储的。系统会对键采用一 种CRC16算法,将键转换成一个数值,然后系统用这个数值取模16384,会得到一个介于0~16383之间的值, 系统会判断这个值对应的哈希槽在哪一台主机上,就会自动切换到主机
这些哈希槽范围是: 0~16383
假设有三台主机:
第一台主机: 0 ~ 5000
第二台主机: 5001 ~ 10000
第三台主机: 10001~16383
十二、哨兵机制
Redis的哨兵机制是一种用于监控和自动故障转移的特性。它由一组称为哨兵(sentinel)的进程组成,这些哨兵进程负责监控Redis主服务器以及其相关的从服务器。
当主服务器出现故障时,哨兵会自动发现并将其中一个从服务器提升为新的主服务器,以确保服务的持续可用性。哨兵还能够监控Redis实例的健康状况,并在必要时执行故障转移操作。
哨兵机制的主要特点包括:
- 监控:哨兵能够定期检查Redis实例的可用性,包括主服务器和从服务器。
- 自动故障转移:当主服务器故障时,哨兵能够自动将其中一个从服务器提升为新的主服务器,并将其他从服务器重新配置为复制新的主服务器。
- 配置提供者:哨兵可以作为配置提供者,将新的主服务器和从服务器的地址和端口信息通知给客户端。
- 选举机制:哨兵使用选举机制来决定哪个从服务器能够成为新的主服务器。
- 哨兵集群:多个哨兵进程可以组成一个哨兵集群,以提高可用性并避免单点故障。
使用哨兵机制可以让Redis实例具有更高的可用性和冗余性,当主服务器出现故障时能够快速进行故障转移,确保服务的持续可用性。