文章目录
1. redis的使用场景
1.1. 项目中用到了redis
1、树形结构 2、角色 权限 菜单 3、用户信息
1.2. redis的数据结构有哪些及其使用场景
1、String:缓存功能、计数器、共享用户session
2、List:粉丝列表、评论列表、消息队列
3、Hash:商品详情
4、Set:抽奖
5、zSet:排行榜、交集 并集 差集的操作
2. redis为什么这么快
redis采用的是基于内存的单进程单线程的kv数据库。
- 完全基于内存操作,查找和操作的时间复杂度都是O(1)。
- 数据结构简单,对应的操作数据也简单。
- 采用单线程,不存在多线程之间的切换而消耗CPU。
- 使用多路IO复用模型,非阻塞IO。
3. redis的异步队列
一般使用list作为队列。其中使用rpush来生产消息,lpop来消费消息。当lpop没有消息的时候,可以使用sleep适当休息一会,稍后再试。
如果不使用sleep,还可以使用blpop,这个指令是在没有消息的时候,会被阻塞,直到消息到来。
4. redis的延时队列
使用zSet作为延时队列。用时间戳作为score,消息内容作为key调用zadd来生产消息,消费者用zrangebyscore获取N秒之前的数据轮询进行处理。
5. 缓存穿透 缓存击穿 缓存雪崩
缓存穿透:key对应的数据在数据源中并不存在,每次针对此key的请求从缓存中获取不到,请求都到数据源,从而可能压垮数据源。
例子:查询id=-1的数据
解决办法:采用布隆过滤器(在缓存之前添加一个布隆过滤器,在查询的时候先去布隆过滤器查询key是否存在,如果不存在就直接返回,存在就走缓存->DB)、将查询为空的结果进行缓存、增加校验
缓存击穿:key对应的数据存在,但在缓存中过期,此时如果有大量的并发请求过来可能会把数据库压垮。
例子:大量并发访问过期的热点数据
解决办法:使用互斥锁(在第一个查询数据的请求上使用一个互斥锁来锁住它,其他线程走到这一步拿不到锁就等着,等第一个线程查询到了数据进行缓存之后,后面的线程就可以直接走缓存了)、设置热点数据永不过期
缓存雪崩:如果大量的key设置为同一时间过期,到过期的那个时间点,redis可能会出现严重的卡顿现象,严重就会发生缓存雪崩。
解决办法:在过期时间上加一个随机值,使得过期时间分散一些。
6. 分布式锁
6.1. 什么是分布式锁
拿setnx来争抢锁,抢到之后,再用expire给锁加一个过期时间以防止忘记释放锁。
6.2. 如果在setnx何expire之间发生意外会怎样?
这样的话,锁就永远得不到释放了。这时可以使用一个set指令,将setnx和expire合成一条指令来使用。
7. 指令
7.1. keys
keys使用遍历算法,用来列出所有满足特定正则字符串规则的key
7.2. scan
scan是通过游标分步进行的,不会阻塞线程;提供了limit参数可以控制每次返回的最大条数。
8. 持久化方式
8.1. 持久化的方式
1、RDB镜像全量持久化:耗费时间长,不实时,在停机的时候会导致大量的数据丢失。
2、AOF增量持久化:记录对内存修改的指令记录。
3、RDB和AOF结合使用
8.2. 优缺点
8.2.1. RDB——优点
- RDB对Redis的性能影响非常小,是因为在同步数据的时候只是fork了一个子进程去做持久化的
- 在数据恢复的时候速度比AOF快。
8.2.2. RDB——缺点
- RDB都是快照文件,默认5分钟或者更久的时间才会生成一次,这就意味着这次同步到下一次同步之间时间的数据很有可能全部丢失。
- 生成数据文件的时候,如果文件很大,客户端会暂停几秒或者几十秒,这样有可能会出现问题。
8.2.3. AOF——优点
- AOF是一秒一次去通过一个后台的线程fsync操作,最多只丢失一秒的数据。
- AOF在对日志文件进行操作的时候是以append-only的方式去写的,是以追加的方式写数据,自然就少了很多磁盘寻址的开销,写入性能高,文件也不容易被破坏。
- AOF的日志是通过一个叫非常可读的方式记录的,这样可以做灾难性数据被误删的紧急恢复。
8.2.4. AOF——缺点
- 一样的数据,AOF文件比RDB文件大。
- AOF的每秒请求数要比RDB低。
8.3. 如何选择?
RDB和AOF结合使用,因为单独使用RDB会导致很多数据丢失,单独使用AOF恢复的速度又很慢。所以首先使用RDB恢复,再使用AOF补全数据。
9. 管道
管道:客户端将多次写合并成一次,服务器端就会收到一条消息,执行一条消息,回复一条消息。将多次IO往返时间缩减为一次
10. redis的同步机制
redis可以使用主从同步和从从同步。第一次同步时,主节点做一次bgsave,并同时将后续修改操作记录到内存buffer,待完成后将RDB文件全量同步到复制节点,复制节点接受完成后将RDB镜像加载到内存。加载完成后,再通知主节点将期间修改的操作记录同步到复制节点进行重放就完成了同步过程。
11. redis集群
redis集群主要使用了Redis Sentinal和Redis Cluster。
Redis Sentinal着眼于高可用,在master宕机时会自动将slave提升为master,继续提供服务。
Redis Cluster着眼于扩展性,在单个redis内存不足时,使用Cluster进行分片存储。
12. 过期策略
12.1. 过期策略方式
定期删除和惰性删除两种
定期删除:默认100s就随机抽取一些设置了过期时间的key,去检查是否过期,过期了就删除。
惰性删除:查询的时候看看是否过期,过期了就删除不返回,没过期就返回。
如果定期没删除也没有进行查询,可以使用内存淘汰机制。
13. 缓存+数据库的读写模式
- 读的时候,先读缓存,缓存没有的话,就读数据库,然后取出数据后放入到缓存中,同时返回响应。
- 更新的时候,先更新数据库,然后再删除缓存,需要使用消息中间件/binlog
- 使用延时双删,先删除缓存,更新数据库之后,使用sleep延时一段时间,在进行缓存的删除
13.1. 更新的时候为什么是删除缓存而不是更新缓存?
有些缓存数据可能是通过计算得到的,而不是直接从数据表中直接取出来的值。
再者就是更新的时候需要每次都更新到缓存中,如果只删除缓存的话,可能很长一段时间才需要读取缓存,这时不管数据库更新了多少次,而只需要缓存一次就好。
14. redis和memcached比较
- redis支持复杂的数据结构;memcached只支持String数据类型。
- redis原生支持集群模式:在 redis3.x 版本中,便能支持 Cluster 模式;Memcached 没有原生的集群模式,需要依靠客户端来实现往集群中分片写入数据。
- 由于redis只是用单核,memcached可以使用多核。所以,在存储小数据的时候,redis的性能比memcached高;而在100k以上的数据时,memcached的性能要高于redis。
不断学习补充中。。。