1.redis数据类型
- String:字符串
- hash:散列
- list:集合
- Set:集合
- Sorted Set: 有序集合
redis是单线程运行,所以是线程安全的
redis持久化方案
- 快照RDB:在指定的时间间隔内生成数据集的时间点快照(point-in-time snapshot),默认Redis 将数据库快照保存在名字为 dump.rdb的二进制文件
- 快照是一个压缩的二进制文件,本质上Mysql 数据保存方式是一样的
- 服务器重启会去读该文件还原数据
- AOF日志:记录服务器执行的所有写操作命令
- AOF 文件中的命令全部以 Redis 协议的格式来保存,新命令会被追加到文件的末尾
- 服务器启动时,通过重新执行这些命令来还原数据集
- 关闭持久化功能
- 关闭后数据只在服务器运行时存在
RDB优点
- 紧凑的文件格式,适合全量复制、存储和传输,并且RDB 文件一旦被创建,就不再修改
- Redis加载RDB恢复数据远远快于AOF的方式
- RDB在保存RDB文件时父进程唯一需要做的就是fork出一个子进程,接下来的工作全部由子进程来做,父进程不需要再做其他IO操作,所以RDB持久化方式可以最大化redis的性能.
缺点
- RDB方式数据没法做到实时持久化,数据句可能丢掉一部分
- 存在新版本不兼容的问题,存储RDB的格式老版本不兼容新版本
- 当数据集非常大时,fork的过程是非常耗时的,可能会导致Redis在一些毫秒级内不能响应客户端的请求对比AOF:AOF也需要fork,但是可以调节重写日志文件的频率来提高数据集的耐久度.
RDB文件替换:服务器要创建一个新的 RDB 文件时, 它先将文件的内容保存在一个临时文件里面, 当临时文件写入完毕时, 程序才使用 rename(2) 原子地用临时文件替换原来的 RDB 文件。因此 复制 RDB 文件都是绝对安全的
触发机制配置:save m n 表示m秒内数据集存在n次修改时,自动触发,常用有如下几种
# 时间策略
save 900 1
save 300 10
save 60 10000
AOF主要解决了数据持久化的实时性,目前是Redis的主流持久化方式
优点:
- 你可以使用不同的fsync策略:无fsync,每秒fsync,每次写的时候fsync.使用默认的每秒fsync策略,出故障后最多丢失一秒的数据
- fsync是由后台线程进行处理的,主线程会尽力处理客户端请求,性能也很好
- 当日志文件过大时会自动进行日志重写: 重写后的新 AOF 文件包含了恢复当前数据集所需的最小命令集合
- 重写过程
- Redis 在创建新 AOF 文件的过程中,会继续将命令追加到现有的 AOF 文件里面
- 新 AOF 文件创建完毕,Redis 就会从旧 AOF 文件切换到新 AOF 文件,并开始对新 AOF 文件进行追加操作。
- 重写过程
- 如果误删数据,可以恢复:只需停机,然后删除命令从日志文件中删除,再次启动是数据自动回复
缺点
- 占用磁盘空间大:对于相同的数据集来说,AOF 文件的体积通常要大于 RDB 文件的体积。
- 根据所使用的 fsync 策略,AOF 的速度可能会慢于 RDB ,关闭AOF日志,熟读和RDB一样快
如果写正在写入是停机后redis可能会拒绝载入文件
- 备份AOF 文件
- Redis 附带的 redis-check-aof 程序,对原来的 AOF 文件进行修复: redis-check-aof –fix
- 重启 Redis 服务器,等待自动才入回复数据
工作原理
AOF 重写和 RDB 创建快照一样,都巧妙地利用了写时复制机制:
- Redis 执行 fork() ,现在同时拥有父进程和子进程
- 子进程开始将新 AOF 文件的内容写入到临时文件
- 对于所有新执行的写入命令,父进程一边将它们累积到一个内存缓存中,一边将这些改动追加到现有 AOF 文件的末尾
- 当子进程完成重写工作时,它给父进程发送一个信号,父进程在接收到信号之后,将内存缓存中的所有数据追加到新 AOF 文件的末尾。
- Redis 原子地用新文件替换旧文件,之后所有命令都会直接追加到新 AOF 文件的末尾
假如AOF和RDB都打开,恢复数据优先使用AOF日志
redis数据备份
数据备份方法:创建一个定期任务(cron job), 每小时将一个 RDB 文件备份到一个文件夹, 并且每天将一个 RDB 文件备份到另一个文件夹
redis使用过程可能出现的问题
击穿:
数据的获取本来应该在缓存获取,结果是redis中没有数据,短时间内大量请求直接从数据库获取
- 解决方案:redis获取数据后主动放到缓存(设定过期时间)
String name = redisUtil.get("name");
if(null==name){//空间检验 获取数据为空
synchronized{//查询数据加锁
name = redisUtil.get("name");//再次获取,防止并发时多个线程都获取到空值,并且都在等待锁,一个线程查完数据库后翻入缓存,再次获取并判断,可以保证数据只查询一次
if(null==name){
name =resourceDao.get("name");
redisUtil.put("name ",name);//数据查询完后放入缓存
}
}
}
雪崩:
缓存雪崩表现在同一时刻缓存大部分key实现或redis挂机,压力全部加载到数据库上
- 情况一:是指在某一个时间段,缓存集中过期失效,大部分是设定缓存时间,并且在同一时刻大部分到期失效,如果客户访问量很大,数据库会有周期性的压力
- 解决方案
- 根据不同类别设置不同的过去时间,或者加上你一个随机因子,尽可能分散缓存过期时间
- 热门信息,缓存时间长一些,冷门短一些
- 解决方案
- 情况二:redis服务器挂机导致:
- 解决方案
- 目前建议是采用redis集群,一台机器挂机至少技能能仍能提供红服务,不至于将压力长时间压在数据库,毕竟全部服务器同时挂机的概率太低了
- 解决方案