欢迎来到无限飞翔,在这里,你会找到许多有趣的技术 : )

Redis 从生米煮成熟饭

开发者头条 80℃ 0评论

Redis为何选用单线程

单线程减少线程上下文切换和锁竞争。

网络IO模型采用IO多路复用,使用EPOLL注册读写事件通知,同步非阻塞。

Redis单线程如何发挥多核CPU优势

在单台服务器上运行多个redis实例。
使用taskset命令,将每个redis实例和cpu核心进行绑定

Redis分布式锁实现

setnx key value
如果key不存在,则创建并赋值。成功返回1 失败返回0。
同时设置过期时间: expire key seconds

也可使用set命令配合NX EX选项一次性设置
SET key value EX 10086 NX

缓存雪崩、缓存击穿、缓存穿透

缓存雪崩: 大量的KEY过期时间过于集中,导致瞬时很多缓存失效,由此可能导致数据库压力陡然升高。
解决方案: 将失效时间随机打乱,如在系统启动预热时设定一定程度上离散的过期时间。

缓存击穿: 缓存中某一个KEY过期失效,如果此时有大量请求过来无法命中缓存的KEY,缓存层像被凿开了一个口子一样流入大量数据库查询请求
解决方案:双重校验方式从数据库中读取数据到缓存。双重校验:第一层查询缓存失败后,进入临界区,保证同时只有一个请求线程读取数据库,进入临界区后再次尝试缓存,仍然没有命中则查询数据库。

缓存穿透: 外部请求不断查询一个系统中不存在的数据,服务无法命中缓存转而每次尝试从数据库中查询。
解决方案

  1. 对查询结果为空key设置值为null的缓存,牺牲缓存空间换响应时间。
  2. 把所有非法的key映射到一个bitmap中,通过bitmap拦截。《布隆过滤器》原理

Redis如何删除过期key

  1. 主动删除:redis 默认每隔一定时间检查已过期key进行删除, 或者内存不足时触发主动删除机制

  2. 惰性删除:在有请求读写key时再检查key是否过期,过期则删除

Redis如何持久化

AOF

AOF(Append Only File ): 记录每次redis的写命令,如对一个key更新10次,记录10条写指令。可以设置每秒一次或者每个写动作发生后追加。
优点: 持久化频率高,异常down机时数据丢失少。
缺点: 文件大,恢复时相对耗时。

Redis默认使用RDB持久化,可同时开启AOF持久化,如下

appendonly yes
appendfilename "appendonly.aof" 

AOF重写

AOF文件体积过大时会进行重写。重写的作用是用一条命令去记录键值对,代替之前记录该键值对的多个命令。如一个key自增100次,原文件记录了100条指令,重写后将原来的指令合并成为最新的一条,由此大大压缩AOF文件体积。

重写采用写时赋值(Copy On Write)原理,不直接操作原文件。

RDB

RDB:快照持久化。在特点时间点保存全量的数据信息。
优点: 恢复时直接将快照文件加载到内存,速度快。
缺点: 因为全量数据量大,持久化频率一般设置较低。异常关机时会丢失上次持久化到关机时刻的变更数据。

如RDB方式配置

save 900 1 #在900s内如果有1条数据被写入,则产生一次快照。  save 300 10#在300s内如果有10条数据被写入,则产生一次快照   
save 60 10000 #在60s内如果有10000条数据被写入,则产生一次快照  stop-writes-on-bgsave-error yes # 如果为yes则表示,当备份进程出错的时候,   主进程就停止进行接受新的写入操作,这样是为了保护持久化的数据一致性的问题。 

bgsave

也可通过basave命令手动触发快照的持久化。bgsave fork出子进程,采用写时复制机制写入。不阻塞主进程的工作(对比save命令)。

AOF和RDB可搭配同时使用,开启AOF时,redis启动默认从AOF日志文件中重建缓存。

Redis集群方案

  1. Sentinel:
    哨兵模式,主要实现高可用。解决Redis原有的主从同步模式,当Master实例故障时导致整个集群无法工作的缺陷。Sentinel是一个独立运行的进程,检测Redis集群状态,如Master因故障下线时则在集群机器中发起选举选出新的Master节点。
  2. Cluster: 解决单台主机的内存容量有限。 Redis集群定义有16384个哈希槽,每个节点负责一段。每个key通过CRC16校验后对16384取模来决定放置哪个分片。

Redis和数据库不一致问题

数据库更新时需要触发缓存更新

如果先删除缓存再进行数据库更新, 可能在数据库更新之前,新的请求进来因为没有命中缓存从数据库中读取旧数据。
如果先进行数据库更新在删除缓存,可能出现数据库写入成功后删除缓存失败。导致缓存仍然是旧数据。

网上流传双删策略: 先删除缓存–> 数据库写入 ——》再次删除缓存。

好处是能数据更新前能预检查下redis工作状态,但是关键的问题:写入后删除缓存时失败的情况仍然可能存在。根本的解决方案应该在写入后删除失败时增加重试机制,或者回滚数据库更新。

Redis内存淘汰策略

Redis使用内存超过 maxmemory 配置大小时触发内存淘汰策略。

  • noeviction:不删除策略,内存达到上限时直接返回错误信息
  • allkeys-random: 针对所有的key,随机删除一部分
  • allkeys-lru: 针对所有的key,优先删除最少使用的
  • volatile-random: 针对设置了过期时间的key,随机删除一部分
  • volatile-ttl: 针对设置了过期时间的key,优先删除最快过期的key

参考

Redis中文官方网站

转载请注明:无限飞翔 » Redis 从生米煮成熟饭

喜欢 (0)or分享 (0)
发表我的评论
取消评论
表情