Redis 是一款高性能、可扩展的 NoSQL 数据库
1、它是内存数据库,速度快
2、它的工作线程worker是单线程 (Redis在6.0版本中引入了多线程IO的功能),,并且redis提供一些机制实现了串行化和原子操作(事务,lua脚本,分布式锁,setnx等一些命令)
3、Redis使用事件驱动的IO模型(epoll)来支撑高并发
4、redis是kv模型,value具有类型结构(string,hash,list,set,zset,bitmap等)
5、redis具有本地方法,计算向数据移动
6、 它的数据是以二进制形式存储的,并且没有什么限制,所以redis是二进制安全的,Value最大512M
1.从服务器向主服务器发送同步命令;
2.主数据库接收到同步命令后,执行 bgsave 命令,在后台生成一个 rdb 文件,并使用一个缓冲区记录从现在开始执行的所有写命令;
3.当主服务器执行完 bgsave 命令后,主服务器会将 bgsave 命令生成的 rdb 文件发送给从服务器;
4.从服务器接收到这个 rdb 文件,然后加载到内存 ;之后主服务器会把刚刚在缓存区的命令同步过来,从服务器就会执行这些命名。(两边就一致了)
5.以上处理完之后,之后主数据库每执行一个写命令,都会将被执行的写命令发送给从数据库。
1.定时删除:在设置键的过期时间的同时,创建一个定时器 timer. 让定时器在键的过期时间来临时,立即执行对键的删除操作。(CPU压力很大,几乎不使用)
2)惰性删除:不去管键有没有过期,但是每次从键空间中获取键时,都检查取得的键是否过期,如果过期的话,就删除该键,返回空(nil);如果没有过期,就返回该键。
3)定期删除:每隔一段时间程序就对redis数据库进行一次检查,删除里面的过期键。至于要删除多少过期键,以及要检查多少个数据库,则由算法决定。
四种常见策略:
1.先删缓存,再更新数据库
2.先更新数据库,再删缓存
3.普通双删(先删除缓存,再更新数据库,再删除缓存)
4.延迟双删
目前最佳的策略是延迟双删,先删除缓存,再更新数据库,再延时3-5秒后再删除缓存,但是极端情况在更新数据库前查询,缓存删除后才放入读取的数据,所以延时双删还是不一定能保证缓存及数据一致,只会最大程度保证数据一致
1 穿透: 恶意请求或者不断访问redis和mysql都没有的数据
(解决办法:将查询的key存入redis的黑名单)
2 击穿:一个热点的key失效了,这时大量的并发请求直接到达数据库.
(解决办法:提前预热,提前加载热点数据到缓存中,避免在高峰期大量请求直接访问数据库。)
3 雪崩:大量key同时失效
(解决办法:错峰设置缓存过期时间,添加一个随机的时间偏移,避免大量的key同一时间失效)
Redi在6.0前是单线程的,它使用一个主线程来处理所有的客户端请求。 在6.0版本后Redis的工作线程是单线程的,但它通过使用非阻塞的I/O多路复用机制(如epoll等)来实现并发处理多个客户端请求。
redis是一个内存数据库,一旦断电或服务器进程退出,内存中的数据将全部丢失,所以需要Redis持久化。Redis持久化就是把数据保存在磁盘上,利用永久性存储介质将数据保存,在特定的时间将保存的数据进行恢复的工作机制
Redis提供两种持久化机制:
RDB恢复速度快,但是因为快照时间有间隔,不能实时备份,有丢失数据的风险
AOF数据安全性高,不易丢数据,数据有序保存,可读性强,但生成文件体积大,且数据恢复速度比RDB慢
可以选择同时使用 RDB 和 AOF 持久化机制,以获得更高的数据可靠性和灵活性,但最好根据应用需求和对数据的要求来选择适合的持久化机制
首先集群实现使用了主从复制机制,主服务器(主节点)负责处理读写操作,从服务器(从节点)复制主节点的数据并处理读操作,如果主节点发生故障,需要手动将一个从节点提升为新的主节点,从而实现故障转移。
在主从复制的基础上,redis可以通过配置哨兵模式来使每个Redis实例都运行一个哨兵进程,哨兵进程负责监视Redis实例(主从服务器)的状态(是否下线或故障),并在主服务器出现故障时自动执行重新配置和重新分配工作负载的操作,来实现故障转移。
代理模式是一种通过代理redis实例(主从服务器)来提供高可用性和负载均衡的集群方案。在代理集群中,客户端连接到代理服务器,代理服务器负责将请求路由到Redis实例上。如果某个实例出现故障,代理服务器将自动切换到其他可用实例。
Redis Cluster集群模式将数据分散在多个节点(服务器)上,以提高可伸缩性和性能。数据被分成多个槽,每个槽由一个节点负责。客户端可以通过与集群中的任意节点通信来访问数据,Redis Cluster将自动将请求路由到正确的节点上。如果一个节点故障,Redis Cluster会自动进行故障转移,并重新分配数据
区别:
范围:
哨兵模式集群只能管理多个Redis实例;
代理模式集群可以管理多个Redis实例,Redis Cluster集群可以管理多个Redis集群(每个集群包含多个Redis实例),它们两种都可以分布在多台机器上。
数据分片:
哨兵模式集群不支持数据分片,所有数据都存储在单个Redis实例上;
代理模式集群支持数据分片和负载均衡,可以将数据分散存储在多个Redis实例上,实现了数据的分布式存储和负载均衡,但没有冗余备份。
Redis Cluster集群支持数据分片和负载均衡,可以将数据分散存储在多个Redis实例和集群上,实现了数据的分布式存储,负载均衡,存储了冗余备份。
故障转移:
哨兵模式集群、Redis Cluster集群和代理模式集群都提供了自动故障转移的功能,都可以监控Redis实例的状态,如果发现主节点宕机则会自动进行故障转移;
不同的是,哨兵模式集群是通过选举新的主节点来实现故障转移,
代理模式集群是通过切换请求路由到新的主节点上来实现故障转移,
Redis Cluster集群是通过切换Redis集群的主节点来实现故障转移
性能:
哨兵模式集群的性能相对较低,所有数据都需要存储在单个Redis实例上;
代理模式集群的性能相对较高,可以将请求分散到多个Redis实例上;
Redis Cluster集群的性能较高,可以将请求分散到多个Redis集群上,更好地利用多台机器的计算资源。
string hash list set zset bitmap
其中string常用于缓存数据,计数器分布式锁等,hash用来存储对象,复杂的缓存数据,list用于消息队列,最新消息,set用于唯一数据存储,共同关注或好友,zset用于排行榜或范围查询等,bitmap一般用于签到
首先查找某个key可以使用keys *,但是因为keys是遍历所有的key来进行匹配,并且redis是单线程的,所以会阻塞,使用scan
Redis 慢日志(Slow Log)是一种用于记录执行时间超过指定阈值的命令的功能。它可以帮助开发人员识别和优化执行时间较长的 Redis 命令,从而提高系统性能。
使用步骤:
1.打开慢日志功能
在 Redis 配置文件(redis.conf)中找到 slowlog-log-slower-than 配置项,设置一个适当的阈值,以毫秒为单位。例如,设置为 10000 表示记录执行时间超过 10 秒的命令。
将 slowlog-max-len 配置项设置为一个合适的值,表示慢日志的最大长度。默认为 128。
2.查看慢日志
使用 SLOWLOG GET 命令可以获取最新的慢日志列表。可以通过指定参数来限制返回的日志数量,例如 SLOWLOG GET 10 表示获取最新的 10 条慢日志。
每条慢日志包含一个唯一的 ID、执行时间、命令和命令参数等信息。
3.清空慢日志
使用 SLOWLOG RESET 命令可以清空慢日志列表。
1.使用Redis实现分布式锁
在 Redis 中可以利用 SETNX(SET if Not eXists)命令实现分布式锁。该命令在键不存在时设置键的值,用于获取锁。
如果 SETNX 命令返回 1,表示成功获取到锁;如果返回 0,表示锁已被其他客户端持有。
在获取到锁后,需要设置一个适当的过期时间,以防止锁被长时间占用。
2.使用ZooKeeper实现
在 ZooKeeper 中可以利用临时顺序节点实现分布式锁。每个客户端在指定的目录下创建一个临时顺序节点,用于表示获取锁的请求。
客户端通过获取目录下所有子节点,并判断自己是否是最小的节点,如果是,则表示成功获取到锁。
在释放锁时,客户端删除自己创建的节点。
注意:无论是Redis还是ZooKeeper都需要考虑:
锁的获取和释放必须是原子操作,避免出现并发问题。
需要设置适当的锁超时时间,以防止锁被长时间占用导致死锁。
需要处理异常情况,确保在发生异常时能够正确释放锁。
考虑使用可重入锁(Reentrant Lock)来支持同一个客户端多次获取锁的情况。
(主要考察要新增一个表)
创建表的时候在一个用户流量较小的时间段(比如凌晨零三点)创建一个新的表,写一段代码去跑一下,将旧的表中的内容写入新的表中。
能停服务的话就尽量停服务,不能听的话就先把大部分数据倒过去,然后快速将新的增量加进去
使用Redis原子操作或者使用Lua脚本:
1.原子操作:
incrby:原子操作,确保并发情况下不会出现竞争条件
get:获取当前库存,递减之前检查当前的库存足够
2.Lua脚本
使用 Lua 脚本可以将多个 Redis 命令组合成一个原子操作,避免了客户端与服务器之间的多次通信。
在 Lua 脚本中,可以使用 Redis 的 EVAL 命令来执行脚本。