redis是什么
本质上是一个 Key-Value 类型的内存数据库 因为是纯内存操作, Redis 的性能非常出色,每秒可以处理超过 10 万次读写操作,是已知性能最快的 Key-Value DB 支持多种数据类型 Redis 的主要缺点是数据库容量受到物理内存的限制,不能用作海量数据的高性能 读写,因此 Redis 适合的场景主要局限在较小数据量的高性能操作和运算上
redis有哪几种数据淘汰策略
1.no-eviction:返回错误当内存限制达到,并且客户端尝试执行会让更多内存被使用的命令。 2.allkeys-lru: 尝试回收最少使用的键( LRU),使得新添加的数据有空间存放。 3.volatile-lru: 尝试回收最少使用的键( LRU),但仅限于在过期集合的键,使得新添加的数据有空间存 放。 4.allkeys-random: 回收随机的键使得新添加的数据有空间存放。 5.volatile-random: 回收随机的键使得新添加的数据有空间存放,但仅限于在过期集合的键。 6.volatile-ttl: 回收在过期集合的键,并且优先回收存活时间( TTL)较短的键,使得新添加的数据有空间 存放。
redis过期键的删除策略
(1) 定时删除:在设置键的过期时间的同时,创建一个定时器 timer). 让定时器在键的过期时间来临时,立即执行对键的删除操作。 (2) 惰性删除:放任键过期不管,但是每次从键空间中获取键时,都检查取得的键是否过期,如果过期的话,就删除该键;如果没有过期,就返回该键。 (3) 定期删除:每隔一段时间程序就对数据库进行一次检查,删除里面的过期键。至于要删除多少过期键,以及要检查多少个数据库,则由算法决定。
Pipeline 有什么好处,为什么要用pipeline?
答:可以将多次 IO 往返的时间缩减为一次,前提是 pipeline 执行的指令之间没有因果相关性。使用 redis-benchmark 进行压测的时候可以发现影响redis 的 QPS 峰值的一个重要因素是 pipeline 批次指令的数目。
说说 Redis 哈希槽的概念?
答:Redis 集群没有使用一致性 hash,而是引入了哈希槽的概念,Redis 集群有 16384 个哈希槽,每个 key 通过 CRC16 校验后对 16384 取模来决定放置哪个槽,集群的每个节点负责一部分 hash 槽
是否使用过 Redis 集群,集群的原理是什么?
1、 Redis sentinel 着眼于高可用,在 master 宕机时会自动将 slave 提升为 master,继续提供服务。 2、Redis Cluster 着眼于扩展性,在单个 redis 内存不足时,使用Cluster 进行分片存储。 3、主从复制
Redis 集群的主从复制模型是怎样的?
答:为了使在部分节点失败或者大部分节点无法通信的情况下集群仍然可用, 所以集群使用了主从复制模型,每个节点都会有 N-1 个复制品.
数据结构
相关语法文档: redisdoc.com/string/gets…
redis试验 try.redis.io/
string
应用场景: 一般常用在需要计数的场景,比如用户的访问次数、热点文章的点赞转发数量等等。
list
双向链表 场景:发布\订阅、队列、栈
hash
适合对象的存储 hash 类似于 JDK1.8 前的 HashMap
set
需要存放的数据不能重复以及需要获取多个数据源交集和并集等场景 类似于hashset
bitmap
使用场景一:用户行为分析 很多网站为了分析你的喜好,需要研究你点赞过的内容。
使用场景二:统计活跃用户 使用时间作为 key,然后用户 ID 为 offset,如果当日活跃过就设置为 1
使用场景三:用户在线状态 只需要一个 key,然后用户 ID 为 offset,如果在线就设置为 1,不在线就设置为 0。
redis单线程
Redis 通过IO 多路复用程序 来监听来自客户端的大量连接(或者说是监听多个 socket),它会将感兴趣的事件及类型(读、写)注册到内核中并监听每个事件是否发生。
redis为什么不使用多线程
不过,Redis 4.0 增加的多线程主要是针对一些大键值对的删除操作的命令,使用这些命令就会使用主处理之外的其他线程来“异步处理”。
大体上来说,Redis 6.0 之前主要还是单线程处理。
那,Redis6.0 之前 为什么不使用多线程?
我觉得主要原因有下面 3 个:
单线程编程容易并且更容易维护; Redis 的性能瓶颈不在 CPU ,主要在内存和网络; 多线程就会存在死锁、线程上下文切换等问题,甚至会影响性能。
Redis6.0 引入多线程主要是为了提高网络 IO 读写性能,因为这个算是 Redis 中的一个性能瓶颈(Redis 的瓶颈主要受限于内存和网络)。
虽然,Redis6.0 引入了多线程,但是 Redis 的多线程只是在网络数据的读写这类耗时操作上使用了,执行命令仍然是单线程顺序执行。因此,你也不需要担心线程安全问题。
Redis 是如何判断数据是否过期的呢?
Redis 通过一个叫做过期字典(可以看作是 hash 表)来保存数据过期的时间。过期字典的键指向 Redis 数据库中的某个 key(键),过期字典的值是一个 long long 类型的整数,这个整数保存了 key 所指向的数据库键的过期时间(毫秒精度的 UNIX 时间戳)。
持久化的方式
快照(snapshotting)持久化(RDB)
Redis 可以通过创建快照来获得存储在内存里面的数据在某个时间点上的副本。Redis 创建快照之后,可以对快照进行备份,可以将快照复制到其他服务器从而创建具有相同数据的服务器副本(Redis 主从结构,主要用来提高 Redis 性能),还可以将快照留在原地以便重启服务器的时候使用。 数据安全性低
AOF(append-only file)持久化
与快照持久化相比,AOF 持久化的实时性更好,因此已成为主流的持久化方案。 (1) AOF 文件比 RDB 文件大,且恢复速度慢。 (2) 数据集大的时候,比 rdb 启动效率低
默认情况下 Redis 没有开启 AOF(append only file)方式的持久化,可以通过 appendonly 参数开启:appendonly yes
拓展:Redis 4.0 对于持久化机制的优化 Redis 4.0 开始支持 RDB 和 AOF 的混合持久化(默认关闭,可以通过配置项 aof-use-rdb-preamble 开启)。
如果把混合持久化打开,AOF 重写的时候就直接把 RDB 的内容写到 AOF 文件开头。这样做的好处是可以结合 RDB 和 AOF 的优点, 快速加载同时避免丢失过多的数据。当然缺点也是有的, AOF 里面的 RDB 部分是压缩格式不再是 AOF 格式,可读性较差。
事务
Redis 可以通过 MULTI,EXEC,DISCARD 和 WATCH 等命令来实现事务(transaction)功能。
1、开始事务(MULTI)。 2、命令入队(批量操作 Redis 的命令,先进先出(FIFO)的顺序执行)。 3、执行事务(EXEC)。
不支持事务的回滚
你可以将 Redis 中的事务就理解为 :Redis 事务提供了一种将多个命令请求打包的功能。然后,再按顺序执行打包的所有命令,并且不会被中途打断。
缓存穿透
请求大量不存在key,请求直接到数据库上 应对办法: 1、缓存无效 key 如果缓存和数据库都查不到某个 key 的数据就写一个到 Redis 中去并设置过期时间, 2、布隆过滤器 但是,需要注意的是布隆过滤器可能会存在误判的情况。总结来说就是: 布隆过滤器说某个元素存在,小概率会误判。布隆过滤器说某个元素不在,那么这个元素一定不在。 github.com/Snailclimb/…
缓存雪崩
缓存在同一时间大面积的失效,后面的请求都直接落到了数据库上,造成数据库短时间内承受大量请求
针对服务不可用的情况
采用 Redis 集群,避免单机出现问题整个缓存服务都没办法使用。 限流,避免同时处理大量的请求。
针对热点缓存失效的情况
设置不同的失效时间,比如随机设置缓存的失效时间。 缓存永不失效。
如何保证缓存和数据库数据的一致性
1、更新 DB,然后直接删除 cache 。 删除失败:异步去重试
2、异步定时从db刷新到cache中