Redis入门
Redis入门
作者:IT王小二
一、Redis的安装
Redis安装请查看Linux安装Redis5.0
。
二、Redis是什么
Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
- Redis安装在磁盘。
- Redis数据存储在内存。
三、快速理解Redis使用
Redis是一种键值对(key-value)高性能缓存数据库,类似于Java中的Map<key, value>
。
四、Redis解决了什么问题
减轻了关系型数据库(MySQL、Oracle...)的压力。
五、Redis特性
1)速度快
内存、单线程、多路复用、协议
2)键值对的数据结构服务器
5种常用数据结构: String hash list set zSet
3)丰富的功能
4)简单稳定
单线程,协议简单
5)持久化 将内存数据写入磁盘
6)主从复制
实现多个相同数据的redis副本
7)高可用和分布式集群
哨兵机制实现高可用,保证redis节点故障发现和自动转移
8)客户端语言多
java、php、python、c、c++、node.js等
六、应用场景
- 缓存数据库: 合理使用缓存加快数据访问速度,降低关系型数据库压力
- 排行榜: 按照热度排名,按照发布时间排行,主要用到列表和有序集合
- 计数器应用: 视频网站播放数,网站浏览数
- 社交网络: 赞、踩、粉丝、下拉刷新
- 消息队列: 发布和订阅
- 其他场景。。
七、redis配置、启动、操作、关闭
可执行文件 | 启动redis |
---|---|
redis-server | 启动redis |
redis-cli | redis命令行客户端 |
redis-benchmark | 基准测试工具 |
redis-check-aof | AOF持久化文件检测和修复工具 |
redis-check-dump/redis-check-rdb | RDB持久化文件检测和修复工具 |
redis-sentinel | 启动哨兵 |
redis-cli相关
1) 停止 redis 服务:redis-cli shutdown
注意:
- 关闭时,断开连接,持久化文件生成,相对安全。
- 使用 kill 方式关闭进程时,不会做持久化,还会造成缓冲区非法关闭,会导致数据丢失。
- 关闭前持久化文件,登录redis-cli客户端,再
shutdown nosave|save
。
2) 重大版本:
- 版本号第二位为奇数,为非稳定版本(2.7、2.9、3.1)。
- 版本号第二位为偶数,为稳定版本(2.6、2.8、3.0)。
- 当前技术版本是下一个稳定版本的开发版本,如2.9是3.0的开发版本。
八、数据结构
更多Redis指令可以访问 http://redisdoc.com/ 查看。
1. String
字符串类型:实际上可以是字符串(包括 XML JSON),还有数字(整形 浮点数),二进制(图片 音频 视频),最大不能超过 512MB 。
设值指令
set age 22 ex 10 // 10秒后过期, ttl age 查询剩余时间
setnx name test // 不存在键name时,返回1设置为成功,返回0失败
获取指令
get age // 存在返回age的值
删除指令
del age // 删除age,返回1
批量操作
mset name wanglei age 22 // 批量set
mget name age // 批量get
计数
incr age // 必须为证书自加1,非整数返回错误,无age键从0开始自增返回1
decr age // 整数age减1
incrby age 2 // 整数age + 2
decrby age 2 // 整数age - 2
incrbyfloat score 1.1 // 浮点型 score + 1.1
追加、长度、截取字符串
set name hello;
append name zhangsan; // 追加字符串,变成 hellozhangsan
set zhangsan "张三";
strlen zhangsan // 字符串长度,结果为6,每个中文占3个字节
set name helloworld;
getrange name 0 2 // 截取字符串,返回hel
补充
- EX seconds : 将键的过期时间设置为 seconds 秒。 执行 SET key value EX seconds 的效果等同于执行 SETEX key seconds value 。
- PX milliseconds : 将键的过期时间设置为 milliseconds 毫秒。 执行 SET key value PX milliseconds 的效果等同于执行 PSETEX key milliseconds value 。
- NX : 只在键不存在时, 才对键进行设置操作。 执行 SET key value NX 的效果等同于执行 SETNX key value 。
- XX : 只在键已经存在时, 才对键进行设置操作。
2. Hash
最大存储512M
设置指令
hset user:1 name wanglei// 成功返回1,失败返回0
读取指令
hget user:1 name // 返回wanglei
计算field个数
hlen user:1 // 返回2
删除field
hdel user:1 name // 返回删除个数
批量
hmset user:2 name wanglei age 23 sex boy //返回OK
hmget user:2 name age sex //返回三行:wanglei 23 boy
其他
判断field是否存在:
hexists user:2 name // 若存在返回1,不存在返回0
获取所有field:
hkeys user:2 // 返回name age sex三个field
获取user:2所有value:
hvals user:2 // wanglei 23 boy
获取user:2所有field与value:
hgetall user:2
整型增加1:
hincrby user:2 age 1 // age+1
浮点型增加2:
hincrbyfloat user:2 age 2 // 浮点型加2
三种方式存储user信息比较
1、原生。
set user:1:name wanglei;
set user:1:age 22;
set user:1:sex boy;
优点:简单直观,每个键对应一个值。 缺点:键数过多,占用内存多,用户信息过于分散,不用于生产环境。
2、将对象序列化存入 redis。
set user:1 serialize(userInfo);
优点:编程简单,若使用序列化合理内存使用率高。 缺点:序列化与反序列化有一定开销,更新属性时需要把 userInfo 全取出来进行反序列化,更新后再序列化到 redis。
3、使用hash类型。
hmset user:1 name wanglei age 23 sex boy
优点:简单直观,使用合理可减少内存空间消耗。 缺点:要控制 ziplist 与 hashtable 两种编码转换,且 hashtable 会消耗更多内存 serialize(userInfo)。
3. List
用来存储多个有序的字符串,一个列表可以存的最大元素:2的23次方减1 。
因为有序,可以通过索引下标获取元素或某个范围内的元素列表,列表元素可以重复。
rpush testlist c b a // 从右向左插入c b a, 返回3
lrange testlist 0 -1 // 从左往右获取列表元素,返回c b a,0 -1为索引下标
lpush testlist 1 2 3 // 从左向右插入1 2 3, 返回6
linsert testlist before 1 0 // 在1之前插入0,返回7,after为之后,使用lrange testlist 0 -1 查看,返回结果为3 2 0 1 c b a
lindex testlist -1 // 返回最右末尾a,-2返回b
llen testlist // 当前列表长度,返回7
lpop testlist // 把最左边的第一个元素删除,返回3
rpop testlist // 把最右边的第一个元素删除,返回a
4. Set
用户标签,社交,查询有共同兴趣爱好的人,智能推荐。
保存多元素,与列表不一样的是不允许有重复元素,且集合是无序,一个集合最多可存2的32次方减1个元素,除了支持增删改查,还支持集合交集、并集、差集。
指令
exists user // 检查user键值是否存在,存在返回1,不存在返回0
sadd user a b c // 向user插入3个元素,返回3
sadd user a b // 若再加入相同的元素,则重复无效,返回0
smembers user // 获取user的所有元素,返回结果无序
srem user a // 返回1,删除a元素
scard user // 返回2,计算元素个数
场景,求共同爱好语言
使用方式,给用户添加标签,或者给标签添加用户。
// 给用户添加标签
sadd user:1:fav java js vue python
sadd user:2:fav vue python node.js
sadd user:3:fav c c++ c#
// 求共同爱好,即求交集
sinter user:1:fav user:2:fav // 返回vue、python
sinter user:1:fav user:2:fav user:3:fav // 返回(empty list or set)
5. zSet
常用于排行榜,如视频网站需要对用户上传视频做排行榜,或点赞数与集合有联系,不能有重复的成员。
指令
zadd user:zan 200 wanglei 120 zhangsan 140 lisi // 增加元素,返回3
zrange user:zan 0 -1 withscores // 查询元素,返回点赞数和成员名称,返回张三 120 lisi 140 wanglei 200
zrank user:zan lisi // 返回名次,返回1,排名为0,1,2
zrevrank user:zan wanglei // 反向排名,点赞越多排名越前,返回0
zadd test:1 nx 100 wanglei // 键test:1必须不存在,主要用于添加
zadd test:1 xx incr 200 wanglei // 键test:1必须存在,主要用于修改,此时300
zadd test:1 xx ch incr -299 wanglei // 返回操作结果1,300-29=1
zcard test:1 // 计算成员个数,返回1
6. list、set、zSet 比较
数据结构 | 是否允许元素重复 | 是否有序 | 有序实现方式 | 应用场景 |
---|---|---|---|---|
list | 是 | 是 | 索引下标 | 时间轴,消息队列 |
set | 否 | 否 | 无 | 标签,共同爱好 |
zSet | 否 | 是 | 分值 | 排行榜,点赞数 |
九、redis数据库管理
命令 | 注释 |
---|---|
select | 选择数据库 |
flushdb | 清空当前数据库 |
flushall | 清空所有数据库 |
dbsize | 查看当前数据库key数量 |
默认支持16个数据库;可以理解为一个命名空间。
跟关系型数据库不一样的点:
- redis 不支持自定义数据库名词。
- 每个数据库不能单独设置授权。
- 每个数据库之间并不是完全隔离的。 可以通过 flushall 命令清空 redis 实例面的所有数据库中的数据。
通过select dbid
去选择不同的数据库命名空间,dbid的取值范围默认是0 -15
十、全局命令
- 查看所有键:
keys *
// 可以查询所有key,也可以模糊搜索,如keys user*,但是线上不推荐使用。 - 键总数:
dbsize
// 如果存在大量键,线上不建议使用。 - 检查键是否存在:
exists key
// 存在返回 1,不存在返回 0。 - 设置键过期时间:
expire username 20
// 设置 username 20秒过期,ttl username 查看剩余时间。 - 间的数据类型:
type username
// 返回string,不存在返回none。
十一、什么是缓存雪崩
为了节约内存,Redis 一般会做定期清理数据,但是因为数据清理之后,如果同一时间并发请求被清理的数据,这时候就会去查询MySQL,但是因为MySQL性能问题,大量的并发请求会导致MySQL崩溃。
解决思路:
- 比如5000个并发请求,上锁,只允许一个线程进入Java代码,然后查询MySQL数据库,将缓存放入redis。
- 解锁,然后剩下的4999个查询redis就不会导致MySQL崩溃了。
十二、什么是缓存穿透
前提:黑客模拟一个不存在的订单号xxx
- Redis中没有这个订单号。
- MySQL中也没有这个值,但是一直被查询。
解决思路:
- 对订单表所有数据查询出来放到布隆过滤器, 经过布隆过滤器处理的数据很小(只存0或1)。
- 查订单表前,先到过滤器里查询当前订单号状态是0还是1, 0的话代表数据库没有数据。
十三、Redis持久化机制
redis是一个支持持久化的内存数据库,也就是说redis需要经常将内存中的数据同步到磁盘来保证持久化,持久化可以避免因进程退出而造成数据丢失。
1. RDB持久化方式
RDB持久化把当前进程数据生成快照(.rdb)文件保存到硬盘的过程,有手动触发和自动触发。
手动触发有save和bgsave两命令 。
- save命令:阻塞当前redis,直到RDB持久化过程完成为止,若内存实例比较大会造成长时间阻塞,线上环境不建议用它。
- bgsave命令:redis进程执行fork操作创建子进程,由子线程完成持久化,阻塞时间很短(微秒级),是save的优化,在执行redis-cli shutdown关闭redis服务时,如果没有开启AOF持久化,自动执行bgsave。
RDB如何恢复
redis.conf文件配置了指定目录,重启redis恢复数据。
RDB持久化优缺点
优点:
- 压缩后的二进制文,适用于备份、全量复制,用于灾难恢复。
- 加载RDB恢复数据远快于AOF方式。
缺点:
- 无法做到实时持久化,每次都要创建子进程,频繁操作成本过高。
- 保存后的二进制文件,存在老版本不兼容新版本rdb文件的问题。
2. AOF持久化
针对RDB不适合实时持久化,redis提供了AOF持久化方式来解决。
- 开启:redis.conf设置:
appendonly yes
(默认不开启,为no) - 默认文件名:appendfilename "appendonly.aof"
AOF持久化流程
- 所有的写入命令(set hset)会append追加到aof_buf缓冲区中。
- AOF缓冲区向硬盘做sync同步。
- 随着AOF文件越来越大,需定期对AOF文件rewrite重写,达到压缩。
- 当redis服务重启,可load加载AOF文件进行恢复。
命令写入(append)、文件同步(sync)、文件重写(BGREWRITEAOF)、重启加载(load)
AOP如何恢复
redis.conf文件配置了指定目录,重启redis恢复数据。
AOP配置详解
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时,重写
3. Redis重启时加载AOF和RDB的顺序
- 当AOF和RDB文件同时存在时,优先加载AOF。
- 若关闭了AOF,加载RDB文件。
- 加载AOF/RDB成功,redis重启成功。
- AOF/RDB存在错误,启动失败打印错误信息。