一、基础
一)、
Redis(Remote Dictionary Server):一个使用C语言编写的、开源的非关系型(NoSql)键值对数据库。
- 键的类型只能是String类型,value的类型支持String、List、Hash、Set、SortedSet五种类型;
- 读操作10万次/秒,写操作8万次/秒;
- 支持事务(所有操作都是原子性的,同时支持几个操作合并后的原子性执行);
- 持久化(支持AOF、RDB两种方式);
- 支持LUA脚本、LRU驱动事件、多种集群方案;
- 支持主从复制,主机会自动将数据同步到从机,可以进行读写分离;
二)、Redis和Memcached的区别:
- Redis支持五种数据类型,Memcached只支持简单的字符串;
- Redis是单核,Memcached是多核。小数据使用Redis性能更高,100k以上的大数据使用Memcached性能更高;
- Redis支持持久化,Memcached不支持持久化;
- Redis支持分布式集群,Memcached不支持分布式(通过分布式一致性hash算法)。
三)、数据类型
Redis五种数据类型的应用场景:
- String:常规计数,例如微博数,粉丝数;
- Hash:例如存储用户对象数据,根据用户ID,查找用户姓名、年龄、生日等信息;
- List:可以轻松的实现消息排序等功能,它的另一个应用就是消息队列;
- Set:可以存储不允许重复的数据,而且提供了判断是否存在某元素的重要接口;
- SortedSet:和Set相比增加了一个权重参数Sort,使得集合中的数据能够按照Sort进行有序排序并且是插入有序的,集自动排序。
四)、完整的Redis请求事件过程
- 一次完整的Redis请求事件过程:客户端到服务端的网络连接-》Redis读写事件发生-》Redis服务端的数据处理(单线程)-》数据返回。
- 客户端和服务器是socket通信方式,socket服务端可以同时监听多个客户端请求,但是Redis服务端处理数据是单线程运行。
- 使用单线程的方式是无法发挥多核CPU的性能的,为了充分利用多核CPU,常常在一台Server上启动多个Redis进程。而为了减少切换的开销,有必要为每个Redis进程指定其运行的CPU。
- 因为Redis是单线程的,所以不用考虑加锁的问题,不会存在死锁导致的性能消耗。
- CPU不是Redis的瓶颈,Redis的瓶颈最有可能的是机器内存大小或者网络带宽。
五)、主从复制
- 主从复制(或称冗余备份、数据冗余、数据备份)可实现容灾快速恢复。
- 主redis中的数据和从redis上的数据保持实时同步,当主redis写入数据时通过主从复制机制会复制到两个从redis服务上。
- 复制操作在Master和Slave上都是非阻塞的,复制时依然可以提供查询操作。
- Slave要删除旧数据,并重新加载新版数据时,会阻塞请求。
六)、读写分离
- 主从架构,可以考虑关闭主服务器的数据持久化功能,只让从服务器进行持久化。这样可以提高主服务器的处理性能。
- 从服务器通常被设置为只读模式,这样可以避免从服务器数据被误修改。
七)、哨兵功能
1、什么是哨兵功能
- 哨兵功能自动恢复:通过sentinel模式启动Redis后,自动监控Master/Slave的运行状态,如果Master异常,则会进行Master-Slave切换,将其中的Slaver作为Master,将之前的Master作为Slave。
- 基本原理是:心跳机制+投票裁决。
- 哨兵必须用三个实例去保证自己的健壮性。如果只有两个哨兵实例分别在Master和一个从机上,Master宕机了,若Master上的哨兵没挂还好说,如果Master整个机器都挂了,那么Master上的哨兵也不能用了,就只剩一个哨兵,这时候无法再分派出一个哨兵去进行故障转移了。
2、哨兵的主要功能
- 集群监控:负责监控Master和Slave进程是否正常工作;
- 消息通知:如果有实例故障,则发消息作为警报通知管理员;
- 故障转移:如果Master故障,则会进行Master-Slave切换;
- 故障转移后,通知客户端新的Master地址;
八)、缓存雪崩
1、什么是缓存雪崩:
缓存雪崩:指缓存同一时间大面积的失效,导致后面的请求都会落到数据库上,造成数据库短时间内承受大量请求(大量的缓存击穿)而崩掉。
2、解决办法:
- 在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量;
- 通过reload机制,预先更新缓存,在即将发生大量并发访问前手动触发加载缓存;
- 设置不同的过期时间,让缓存失效时间点尽量均匀点;
- 做二级缓存或者双缓存策略;
九)、缓存穿透
1、什么是缓存穿透
缓存穿透:指缓存和数据库中都没有的数据,导致所有的请求都落到数据库上,造成数据库短时间内承受大量请求而崩掉。
2、解决办法
- 校验用户是否合法;
- 数据库没有读取到的数据,返回为key-null,有效时间设置短一点(否则影响正常使用),可以防止短时间内反复同一个key攻击;
- 采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被bitmap过滤掉;
十)、缓存击穿
1、什么是缓存击穿
缓存击穿:指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力。
和缓存雪崩不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。
2、解决办法
- 设置热点数据永不过期;
- 加互斥锁;
十一)、缓存预热
1、什么是缓存预热
缓存预热:指系统上线后,将相关的缓存数据直接加载到缓存系统。这样就可以避免在用户请求的时候,先查询数据库,然后再将数据缓存的问题,用户直接查询事先被预热的缓存数据!
2、解决方案
- 直接写个缓存刷新页面,上线时手动操作一下;
- 数据量较小的,可以在项目启东市自动进行加载;
- 定时刷新缓存;
十二)、Redis缓存更新策略
1、常见策略:
- 惰性删除:当读/写一个已经过期的 key 时,会触发惰性删除策略,直接删除掉这个过期 key ,并按照 key 不存在去处理。惰性删除,对内存不太好,已经过期的 key 会占用太多的内存。
- 定期删除:每隔一段时间,就会对 Redis 进行检查,主动删除一批已过期的 key。
十三)、缓存降级
1、什么是缓存降级
缓存降级:指当访问量剧增、服务出现问题(如响应时间慢或不响应)或非核心服务影响到核心流程的性能时,仍然需要保证服务还是可用的,即使是有损服务。系统可以根据一些关键数据进行自动降级,也可以配置开关实现人工降级。
降级的最终目的是保证核心服务可用,即使是有损的。而且有些服务是无法降级的(如加入购物车、结算)。
十四)、持久化
1、什么是持久化
按照一定的时间将内存的数据以快照的形式保存到磁盘中。
2、两种持久化方案
- RDB是Redis默认的持久化方式。按照一定的时间将内存的数据以快照的形式保存到硬盘中,对应产生的数据文件为dump.rdb。通过配置文件中的save参数来定义快照的周期。
- AOF持久化(即Append Only File持久化),则是将Redis执行的每次写命令记录到单独的日志文件中,当重启Redis会重新将持久化的日志中文件恢复数据。
3、优缺点比较
- 同数数量时,AOF占磁盘空间大于RDB;
- 从数据回复速度上来说,AOF是将操作日志记录下来,所以备份快,恢复慢;
- 数据安全性上,AOF记录了操作日志,所以数据更加完整,不容易丢失;
十五)、Redis的事务
- Redis的事务具有一致性和隔离性;
- Redis的事务隔离性:Redis是单线程程序,并且它保证在执行事务时,不会对事务进行中断,事务可以运行直到执行完所有事务队列中的命令为止。因此Redis的事务具有隔离性。
- Redis中单条命令是原子性执行的,但事务不保证原子性,且没有回滚。事务中任意命令执行失败,其他命令仍会被执行。
十六)、keys和scan
问题示例:
- keys会造成线程阻塞,它会一直堵塞到指令执行完毕为止,容易造成用户线程缓慢或长时间无反应问题;
- scan是利用游标, 迭代每次返回一部分数据,所以不会造成阻塞问题。最后将查询的结果进行整合并返回,缺点是容易出现重复数据,需要在逻辑层进行去重处理,而且消耗时间比keys长;
十七)、如何解决数据不一致问题
- 如果服务对耗时不敏感,可以增加重试;
- 如果耗时敏感,可以通过异步补偿来处理失败的更新
十八)、Redis如何进行数据同步
二、高级用法