- Redis是什么
- Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API
- Redis安装在磁盘
- Redis数据存储在内存
- Redis特性
- 速度快
- 内存、单线程、IO多路复用、协议简单
- 键值对的数据结构服务器
- key是简单的字符串,越短小精悍越好,value是String、Hash、List、set、zset
- 丰富的功能
- 与Memcache区别,Memcache不能持久化并且只能是字符串
- 简单稳定:因为单线程、协议简单且持久化
- 持久化:redis需要经常将内存中的数据同步到磁盘来保证持久化
- 主从复制
- 高可用和分布式转移
- 客户端语言多
- 速度快
- 使用场景
- 缓存数据库
- 排行榜
- 计数器应用
- 社交网络:贴标签
- 消息队列
- 数据结构
- 字符串
- set age 23 ex 10,10秒后过期
- setnx name test,不存在name时,返回1设置成功,返回0说明存在插入失败
- 批量设值:mset country china city beijing
- 批量获取:mget country city address //返回china beigjin, address为nil
- 计数
- incr age //必须为整数自加1,非整数返回错误,无age键从0自增返回1
- decr age //整数age减1
- incrby age 2 //整数age+2
- 字符串追加截取
- set name hello;append name world //追加后成helloworld
- set hello "世界";strlen hello //结果6,每个中文占3个字节
- set name helloworld ; getrange name 2 4//返回 llo
- hash的命令
- 是一个string类型的field和value的映射表,hash适合用于存储对象
- 命令 hset key field value
- 设值:hset user:1 name james
- 批量设值:hmset user:2 name james age 23 sex boy
- 增加1:hincrby user:2 age 1
- 列表:用来存储多个有序的字符串,一个列表最多可存2的32次方减1个元素
- 可以通过索引下标获取元素或某个范围内元素列表,元素可以重复
- rpush james c b a //依次向右插入c b a, 返回值3
- lrange james 0 -1 //从左到右获取列表所有元素 返回 c b a
- set:保存多元素,与列表不一样的是不允许有重复元素,且集合是无序,一个集合最多可存2的32次方减1个元素,除了支持增删改查,还支持集合交集、并集、差集
- 场景:用户标签,社交,查询有共同兴趣爱好的人,智能推荐
- exists user //检查user键值是否存在
- sadd user a b c//向user插入3个元素,返回3
- smembers user //获取user的所有元素,返回结果无序
- srem user a //返回1,删除a元素
- scard user //返回2,计算元素个数
- 有序集合
- 场景:常用于排行榜,如视频网站需要对用户上传视频做排行榜,或点赞数与集合有联系,不能有重复的成员
- zadd user:zan 200 james 120 mike 100 lee
- zrange test:1 0 -1 withscores //查看点赞(分数)与成员名
- 字符串
- 三种方案实现用户信息存储优缺点
- 原生
- 优点:简单直观,每个键对应一个值
- 缺点:键数过多,占用内存多,用户信息过于分散,不用于生产环境
- 对象序列化存入redis
- 优点:编程简单,若使用序列化合理内存使用率高
- 缺点:序列化与反序列化有一定开销,更新属性时需要把对象全取出进行反序列化,更新后再序列化到redis
- 使用hash类型
- 简单直观,使用合理可减少内存空间消耗
- 缺点:要控制ziplist与hashtable两种编码转换,且hashtable会消耗更多内存Serialize(userInfo)
- 原生
- Redis数据库管理
- 默认支持16个数据库;可以理解为一个命名空间
- 跟关系型数据库不一样的点
- redis不支持自定义数据库名词
- 每个数据库不能单独设置授权
- 每个数据库之间并不是完全隔离的。 可以通过flushall命令清空redis实例面的所有数据库中的数据
- 通过 select dbid 去选择不同的数据库命名空间 。 dbid的取值范围默认是0 -15
- 常见问题
- 缓存雪崩
- 当查询key=james的值,此时Redis没有数据,如果有5000个用户并发来查询key=james,全到Mysql里去查, Mysql会挂掉,造成雪崩
- 缓存穿透
- 一个值被查询,Redis中无此值,Mysql中也无此值,但一直被查询,拖垮数据库
- 解决方案
- 对订单表所有数据查询出来放到布隆过滤器,经过布隆过滤器处理的数据很小(只存0或1)
- 每次查订单表前,先到过滤器里查询当前订单号状态是0还是1, 0的话代表数据库没有数据
- 缓存雪崩
- Redis持久化机制
- RDB持久化
- 把当前进程数据生成快照(.rdb)文件保存到硬盘的过程,有手动触发和自动触发
- save命令:阻塞当前Redis,直到RDB持久化过程完成,若内存实例比较大会造成长时间阻塞,线上环境不建议用
- bgsave命令:redis进程执行fork操作创建子进程,由子线程完成持久化,阻塞时间很短(微秒级),是save的优化,在执行redis-cli shutdown关闭redis服务时,如果没有开启AOF持久化,自动执行bgsave
- RDB持久化
- 优点
- 压缩后的二进制文,适用于备份、全量复制,用于灾难恢复
- 加载RDB恢复数据远快于AOF方式
- 缺点
- 无法做到实时持久化,每次都要创建子进程,频繁操作成本过高
- 保存后的二进制文件,存在老版本不兼容新版本rdb文件的问题
- AOF持久化
- 针对RDB不适合实时持久化,redis提供了AOF持久化方式来解决
- 类似于执行语句的日志
- 配置
- appendonly yes //启用aof持久化方式
- # appendfsync always //每收到写命令就立即强制写入磁盘,最慢的,但是保证完全的持久化,不推荐使用
- appendfsync everysec //每秒强制写入磁盘一次,性能和持久化方面做了折中,推荐
- no-appendfsync-on-rewrite yes //正在导出rdb快照的过程中,要不要停止同步aof
- auto-aof-rewrite-percentage 100 //aof文件大小比起上次重写时的大小,增长率100%时,重写
- auto-aof-rewrite-min-size 64mb //aof文件,至少超过64M时,重写
- 如何恢复
- 设置appendonly yes;
- 将appendonly.aof放到dir参数指定的目录;
- 启动Redis,Redis会自动加载appendonly.aof文件