第一章 Redis介绍
1.1 Redis是什么
Redis是一款开源的,ANSI C语言编写的,高级键值(key-value)缓存和支持永久存储NoSQL数据库产品。
Redis采用内存(In-Memory)数据集(DataSet) 。支持多种数据类型。
redis中的值可以有string,hash,list,set,zset,geo等多种数据结构和算法组成。
不仅如此,Redis还可以将内存中的数据利用快照和日志的形式保存到硬盘上。
Redis还提供了键过期,发布订阅,事务,流水线等附加功能。
1.2 Redis特性
1)高速读写
2)数据类型丰富
3)支持持久化
4)多种内存分配及回收策略
5)支持事物
6)消息队列、消息订阅
7)支持高可用
8)支持分布式分片集群
- 缓存穿透\雪崩
10)Redis API
1.3 Redis应用场景(面试题)
redis的作用:可以作为缓存数据库,MySQL数据库的补充,应用优先在redis取值,redis取到值,则返回,如果没取到值,则到MySQL取值,然后应用转义取到的值存到redis
-
缓存-键过期时间功能实现
- 缓存session会话。访问网站保存cook信息,一整天登录都不需要输入账号密码,第二天要输入,因为设置key过期时间为24小时。
- 作为mysql的缓存。缓存用户信息,先在redis缓存请求查找,找不到再去mysql查,查到然后回写到redis
- 商城优惠卷过期时间。设置优惠卷过期时间
-
排行榜-列表&有序集合
- 热度排名排行榜,帖子排名,热度排名
- 发布时间排行榜
-
计数器应用-天然支持计数器
- 帖子浏览数
- 视频播放次数
- 商品浏览数
- 点赞/点踩
-
社交网络-集合,搜集集合,进行操作
- 踩/赞,共同粉丝,共同好友/共同喜好,推送,打标签
-
消息队列系统-发布订阅
- 配合elk实现日志收集
1.4 企业缓存数据库解决方案对比
Memcached:
- 优点:高性能读写、单一数据类型、支持客户端式分布式集群、一致性hash多核结构、多线程读写性能高。
- 缺点:无持久化、节点故障可能出现缓存穿透、分布式需要客户端实现、跨机房数据同步困难、架构扩容复杂度高
Redis:
- 优点:高性能读写、多数据类型支持、数据持久化、高可用架构、支持自定义虚拟内存、支持分布式分片集群、单线程读写性能极高
- 缺点:多线程读写较Memcached慢
Tair:
- 优点:高性能读写、支持三种存储引擎(ddb、rdb、ldb)、支持高可用、支持分布式分片集群、支撑了几乎所有淘宝业务的缓存。
- 缺点:单机情况下,读写性能较其他两种产品较慢
对比结论:
1.Memcached:适合多用户访问,每个用户少量RW。
应用场景:多核的缓存服务,更加适合于多用户并发访问次数较少的应用场景
2.Redis:适合少量用户访问,每个用户大量RW。
应用场景:单核的缓存服务,单节点情况下,更加适合于少量用户,多次访问的应用场景。
redis一般在企业中,是单机多实例架构,配合redis集群出现
第二章 Redis安装部署
2.1 目录规划
### redis下载目录
/data/soft/
### redis安装目录
/opt/redis_cluster/redis_{PORT}/{conf,logs,pid}
### redis数据目录
/data/redis_cluster/redis_{PORT}/redis_{PORT}.rdb
### redis运维脚本
/root/scripts/redis_shell.sh
2.2 安装命令
[root@db01 ~]# tail -3 /etc/hosts
10.0.0.51 db01
10.0.0.52 db02
10.0.0.53 db03
mkdir -p /data/soft
mkdir -p /data/redis_cluster/redis_6379
mkdir -p /opt/redis_cluster/redis_6379/{conf,pid,logs}
cd /data/soft/
wget http://download.redis.io/releases/redis-3.2.9.tar.gz
tar zxf redis-3.2.9.tar.gz -C /opt/redis_cluster/
ln -s /opt/redis_cluster/redis-3.2.9/ /opt/redis_cluster/redis
cd /opt/redis_cluster/redis
make && make install
#make的作用是生成二进制文件
#make install 的作用是把源码目录里二进制文件copy到/usr/local/bin/目录下
2.3 配置文件
cat >/opt/redis_6379/conf/redis_6379.conf <<EOF
#以守护进程模式启动
daemonize yes
#绑定的主机地址
bind 127.0.0.1 10.0.0.51
#监听端口
port 6379
#pid文件和日志文件的保存地址
pidfile /opt/redis_6379/pid/redis_6379.pid
logfile /opt/redis_6379/logs/redis_6379.log
#本地数据库的目录
dir /data/redis_6379
#指定本地持久化文件的文件名,默认是dump.rdb
dbfilename redis_6379.rdb
EOF
2.4 redis客户端常用命令
#指定配置文件启动redis
redis-server /opt/redis_6379/conf/redis_6379.conf
#检查是否启动
ps -ef|grep redis
netstat -lntup|grep redis
#进入redis
redis-cli
-p 6379 //指定端口号
-h //指定连接地址
-a //指定连接密码
# 无交互执行redis命令
redis-cli set num 10
# 批量执行redis命令,将命令写入文件中
cat /tmp/1.txt |redis-cli
#关闭redis
redis-cli -h db01 shutdown
2.5 redis安全配置
vim /opt/redis_6379/conf/redis_6379.conf //redis配置文件
1) #保护模式,是否只允许本地访问
protected-mode yes/no 禁止
2) 指定IP进行监听
bind 10.0.0.51 127.0.0.1
3) #增加密码
requirepass 123456
#增加密码后,插入会报错
[root@db01 redis]# redis-cli
127.0.0.1:6379> set name zhangsan
(error) NOAUTH Authentication required.
#密码认证方式1
[root@db01 redis]# redis-cli
127.0.0.1:6379> AUTH 123456
127.0.0.1:6379> set name zhangsan
OK
#密码认证方式2
[root@db01 redis]# redis-cli -a 123456
127.0.0.1:6379> set name lisi
OK
第三章 redis基本操作命令
3.1 全局命令
1) 写入key
set k1 v1
set k2 v2
set k3 v3
2) 查看所有的key!
keys * //十分危险的命令,线上禁止使用
3) 查看有多少个key,注意,是估值
DBSIZE //命令在计算键总数时不会遍历所有键,而是直接获取Redis内置的键总数变量
4) 查看是否存在这个KEY
EXISTS k1
EXISTS k1 k2 k3
# EXISTS返回状态码:
0 表示这个key不存在
1 表示这个key存在
N 表示N个key存在
5) 删除key
DEL k1
DEL k1 k2 k3
# DEL返回状态码:
0 表示这个key不存在
1 表示这个key存在,并且删除成功
N 表示有的N个key存在,并且删除N个Key
6) 设置过期时间
EXPIRE k1 100
# EXPIRE返回状态码:
0: 表示这个key不存在
1: 表示这个key存在,并且设置过期时间成功
7) 取消过期时间,不修改key原来的值
PERSIST k1 //重复执行会刷新过期时间
8) 查看key是否过期
TTL k1
# TTL返回状态码:
-1 :这个key存在,并且永不过期
-2 :这个key不存在
N :这个key存在,并且在N秒后过期
# TTL应用,用脚本循环检查优惠劵状态码是否为-1
# TTL结论:
过期后的key直接会被删除
3.2 在线查看和修改配置
#查看配置文件中的监听地址
127.0.0.1:6379> CONFIG GET bind
1) "bind"
2) "127.0.0.1 10.0.0.51"
#查看dir
127.0.0.1:6379> CONFIG GET dir
1) "dir"
2) "/etc/redis/6379"
#查看所有配置
127.0.0.1:6379> CONFIG GET *
#修改密码配置,即时生效,临时修改,重启失效
127.0.0.1:6379> CONFIG SET requirepass 123
OK
#测试修改后连接
[root@db01 redis]# redis-cli -a 123
127.0.0.1:6379> set age 18
OK
#查看配置文件
[root@db01 redis]# cat /etc/redis/6379/redis.conf
daemonize yes
port 6379
logfile /etc/redis/6379/redis.log
dir /etc/redis/6379
dbfilename dump.rdb
bind 127.0.0.1 10.0.0.51
requirepass 123456 //可以看出,配置文件中是没有改变的,只要redis不重启,密码就是新改的
3.3 字符串
Redis并不是简单地key-value存储,实际上他是一个数据结构服务器,支持不同类型的值.
Redis Strings
这是最简单的Redis类型,如果你只用这种类型,Redis就像一个持久化的memcache服务器(注:memcache的数据仅保存在内存中,服务器重启后,数据将丢失.)
1) 设置一个key
set k1 v1
#v1是字符串类型
redis-cli k1 v1 //命令行设置key
redis-cli set txt $(cat wenming.txt) //在命令行设置txt,值为wenming.txt文件内容
2) 查看一个key
get k1
3) 设置多个key
MSET k1 v1 k2 v2 k3 v3
4) 查看多个key
MGET k1 k2 k3
5) 天然计数器
加1:
set k1 1
INCR k1
get k1
# 加N:
INCRBY k1 100
# 减1:
INCRBY k1 -1
# 减N:
INCRBY k1 -N
3.4 列表
列表:一个key,有多个值
# 插入列表:
LPUSH:从列表左侧插入数据
RPUSH:从列表右侧插入数据
LPUSH list1 A
RPUSH list1 D
# 查看列表的长度:
LLEN list1
# 查看列表的内容:
LRANGE list1 0 -1 #0表示起始位置 -1表示终止位置
1) "C"
2) "B"
3) "A"
4) "D"
# 删除列表元素:
LPOP: 从列表左侧删除,每次删除一个
RPOP: 从列表右侧删除,每次删除一个
LPOP list1
RPOP list1
# 删除列表内容:
DEL list1
3.5 哈希
Hash由键值对组成
HMSET指令设置hash中的多个字段
HGET查看单个字段.
HMGET查看一系列的字段
# hash生成格式:HMSET key 字段 value 字段 value
HMSET user:1 name xiaozhang job it age 28 //可以理解为user:1为key ,后面内容为值;H表示hash,M表示多条
HMSET user:3 name def job it age 28
# 查看hash里的一个值
HMGET user:1 name
# 查看hash里的多个值
HMGET user:1 name age job
# 查看hash里的所有的值
HGETALL user:1
mysql数据和redis哈希对比:
-
mysql.user表
uid name job age
1 xiaozhang it 28
2 xiaoya it 25
3 yazhang it 29 -
redis缓存mysql数据
名字 key1 key1值 key2 k2值 key3 k3值
uid:1 name xiaozahng job it age 28
uid:2 name xiaoya job it age 28
uid:3 name yazahng job it age 28
3.6 集合
创建集合,集合里不允许有重复的值
db01:6379> SADD set1 1 2 3 //set1为集合名 1,2,3 为集合的值
(integer) 3
db01:6379> SADD set2 1 3 5 7
(integer) 4
查看集合的成员: member 成员
db01:6379> SMEMBERS set1
1) "1"
2) "2"
3) "3"
db01:6379> SMEMBERS set2
1) "1"
2) "3"
3) "5"
4) "7"
SDIFF查看集合的差集,以前面一个集合为基准对比后面的,前面有,后面没有则选出来
db01:6379> SDIFF set1 set2
1) "2"
db01:6379> SDIFF set2 set1
1) "5"
2)"7"
查看集合的交集
db01:6379> SINTER set1 set2
1) "1"
2) "3"
3) "5"
查看集合的并集,并去重
db01:6379> SUNION set1 set2
1) "1"
2) "2"
3) "3"
4) "5"
5) "7"
db01:6379> SUNION set1 set2 set3
1) "1"
2) "2"
3) "3"
4) "5"
5) "7"
6) "9"
有序集合,全部是以z开头
# 添加成员格式
zadd key score member //key为集合名,score 分数 member 成员
zadd linux6 100 banzhang
zadd linux6 99 xuewei 10 xiaohu 150 chaoyi
# 计算成员个数
zcard linux6
# 查看某个成员分数
zscore key member
zscore linux6 banzhang
# 计算成员排名
zrank key member //升序排名,key为集合名,member为成员
zrevrank key member //降序排名
# 增加成员分数
zincrby key increment member //increment为增加或者减少的值,可为负。member为成员
zincrby linux6 1 xuewei //为xuewei增加1
# 返回指定排名范围的成员
zrang key start end [wishscores] //升序,如果加上wishscores会显示分数,可不加wishscores
zrevrange key start end [wishscores] //降序
zrange linux6 0 2 wishscores
# 返回指定分数范围的成员
zrangebyscore key min max [wishscores] [limit offect count]
zrevrangebyscore key max min [wishscores] [limit offect count]
zrangebyscore linux6 100 200 withscores
ZREVRANGEBYSCORE linux6 200 99 withscores
# 返回指定分数范围成员个数
zount key min max
zcount linux6 100 200
# 删除成员
zrem key member
zrem user:ranking oldzhang
第四章 Redis持久化
什么是持久化?
持久化:就是将内存中的数据,写入到磁盘上,并且永久存在的。
4.1 RDB持久化
RDB持久化介绍:可以在指定的时间间隔内生成数据集的时间点快照(point-in-time snapshot)。
- 优点:速度快,适合于用作备份,主从复制也是基于RDB持久化功能实现的。
- 缺点:会有数据丢失、导致服务停止几秒
RDB持久化核心配置参数
#编辑配置文件
[root@db01 redis]# vim /etc/redis/6379/redis.conf
# 持久化数据文件存储位置
dir /etc/redis/6379
#rdb持久化数据文件名,重启时会将redis_6379.rdb文件载入内存
dbfilename dump.rdb
# 触发条件不宜太细,否则成本过高
save 900 1 //持久化触发的条件,如果900秒内,写入1个key,触发一次
save 300 10 //如果300秒内,写入10个key,触发一次
save 60 10000 //如果60秒内,有10000个key发生改变,触发一次
4.2 AOF持久化
AOF(append only file)记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集。 AOF 文件中的命令全部以 Redis 协议的格式来保存,新命令会被追加到文件的末尾。
- 优点:可以最大程度保证数据不丢失
- 缺点:日志记录量级比较大
# 修改配置文件
[root@db01 redis]# vim /etc/redis/6379/redis.conf
appendonly yes //是否打开aof日志功能
appendfsync always //每1个命令,都立即同步到aof
appendfsync everysec //每秒写1次
appendfsync no //写入工作交给操作系统,由操作系统判断缓冲区大小,统一写入到aof.
4.3 redis持久化结论:
- 执行shutdown的时候,内部会自动执行持久化
- pkill kill killall 都类似于执行shutdown命令.会执行持久化,kill -9 不会持久化
- 恢复的时候,rdb文件名称要和配置文件里写的一样
- 如果没有配置save参数,执行shutdown不会自动bgsave持久化
- 如果没有配置save参数,可以手动执行bgsave触发持久化保存
4.4 面试题
-
redis 持久化方式有哪些?有什么区别?
rdb:基于快照的持久化,速度更快,一般用作备份,主从复制也是依赖于rdb持久化功能
aof:以追加的方式记录redis操作日志的文件。可以最大程度的保证redis数据安全,类似于mysql的binlog -
如果写入数据,没有触发持久化条件,关闭redis会不会持久化?
答:应该问怎么关? shutdown,pkill,kill,killall会持久化,kill -9不会持久化
4.5 RDB和AOF我应该用哪一个?
- 一般来说,如果想达到足以媲美 PostgreSQL 的数据安全性, 你应该同时使用两种持久化功能。
- 如果你非常关心你的数据,但仍然可以承受数分钟以内的数据丢失, 那么你可以只使用 RDB 持久化。
- 有很多用户单独使用AOF,但是我们并不鼓励这样,因为时常进行RDB快照非常方便于数据库备份,启动速度也较之快,还避免了AOF引擎的bug。
- 个人感触:在企业中,通常都使用RDB来做持久化,因为一般redis是在做MySQL的缓存,就算缓存数据丢失,真实的数据还是在MySQL中,之所以用缓存是为了速度,性能而考虑,所以还是建议使用RDB持久化,相对来说会好一些,除非专门用redis来做一个key:value的数据库,而且数据很重要,那么可以考虑使用AOF
4.6 如果 AOF 文件出错了,怎么办?
服务器可能在程序正在对AOF文件进行写入时停机,如果停机造成了AOF文件出错,那么 Redis 在重启时会拒绝载入这个 AOF 文件,从而确保数据的一致性不会被破坏。
当发生 AOF 文件出错时,可以用以下方法来修复出错的 AOF 文件:
1、为现有的 AOF 文件创建一个备份。
2、使用 Redis 附带的 redis-check-aof 程序,对原来的AOF 文件进行修复。redis-check-aof --fix
3、使用 diff -u 对比修复后的 AOF 文件和原始 AOF 文件的备份,查看两个文件之间的不同之处。
4、重启 Redis 服务器,等待服务器载入修复后的 AOF 文件,并进行数据恢复。
4.7 备份 Redis 数据
- Redis 对于数据备份是非常友好的,因为你可以在服务器运行的时候对 RDB 文件进行复制: RDB 文件一旦被创建,就不会进行任何修改。
- 当服务器要创建一个新的 RDB 文件时,它先将文件的内容保存在一个临时文件里面,当临时文件写入完毕时,程序才使用临时文件替换原来的 RDB 文件。
- 这也就是说,无论何时, 复制 RDB 文件都是绝对安全的。
以下是我们的建议:
- 创建一个定期任务(cron job), 每小时将一个 RDB 文件备份到一个文件夹, 并且每天将一个 RDB 文件备份到另一个文件夹。
- 确保快照的备份都带有相应的日期和时间信息, 每次执行定期任务脚本时, 使用 find 命令来删除过期的快照: 比如说, 你可以保留最近 48 小时内的每小时快照, 还可以保留最近一两个月的每日快照。
- 至少每天一次, 将 RDB 备份到你的数据中心之外, 或者至少是备份到你运行 Redis 服务器的物理机器之外。
4.8 RDB与AOF高级配置
RDB持久化高级配置
[root@db01 redis]# vim /etc/redis/6379/redis.conf
#后台备份进程出错时,主进程停不停止写入? 主进程不停止容易造成数据不一致
stop-writes-on-bgsave-error yes
#导出的rdb文件是否压缩 如果rdb的大小很大的话建议这么做
rdbcompression yes
#导入rbd恢复时数据时,要不要检验rdb的完整性 验证版本是不是一致
rdbchecksum yes
AOF持久化高级配置
[root@db01 redis]# vim /etc/redis/6379/redis.conf
#正在导出rdb快照的过程中,要不要停止同步aof
no-appendfsync-on-rewrite yes/no
#aof文件大小比起上次重写时的大小,增长率100%时重写,缺点:业务开始的时候,会重复重写多次
auto-aof-rewrite-percentage 100
#aof文件,至少超过64M时,重写
auto-aof-rewrite-min-size 64mb
第五章 发布订阅

- redis 发布消息通常有两种模式;redis不会对发布的消息持久化
队列模式
发布-订阅模式
任务队列的好处:
1、松耦合
2、已于扩展
- 发布订阅:其实从Pub/Sub的机制来看,它更像是一个广播系统,多个订阅者可以订阅多个频道,多个出版人可以往多个频道中发布消息。
subscriber:收音机,可以收到多个频道,并以队列方式显示
publisher:电台,可以往不同的FM频道中发消息
channel:不同频率的FM频道
一个发布者,多个订阅者模型
应用:通知、公告
多个发布者,一个订阅者模型
应用:排行榜,投票,计数
多个发布者,多个订阅者模型
应用:群聊、聊天
PUBLISH channel msg
将信息 message 发送到指定的频道 channel
SUBSCRIBE channel [channel ...]
订阅频道,可以同时订阅多个频道
UNSUBSCRIBE [channel ...]
取消订阅指定的频道, 如果不指定频道,则会取消订阅所有频道
PSUBSCRIBE pattern [pattern ...]
订阅一个或多个符合给定模式的频道,每个模式以 * 作为匹配符,比如 it* 匹配所 有以 it 开头的频道( it.news 、 it.blog 、 it.tweets 等等), news.* 匹配所有 以 news. 开头的频道( news.it 、 news.global.today 等等),诸如此类
PUNSUBSCRIBE [pattern [pattern ...]]
退订指定的规则, 如果没有参数则会退订所有规则
PUBSUB subcommand [argument [argument ...]]
查看订阅与发布系统状态
注意:使用发布订阅模式实现的消息队列,当有客户端订阅channel后只能收到后续发布到该频道的消息,之前发送的不会缓存,必须Provider和Consumer同时在线。
发布订阅例子:
窗口1:
127.0.0.1:6379> SUBSCRIBE baodi
窗口2:
127.0.0.1:6379> PUBLISH baodi "jin tian zhen kaixin!"
订阅多频道:
窗口1:
127.0.0.1:6379> PSUBSCRIBE wang*
窗口2:
127.0.0.1:6379> PUBLISH wangbaoqiang "jintian zhennanshou "
第六章 Redis事务
redis的事务是基于队列实现的。
mysql的事务是基于事务日志和锁机制实现的。
redis是乐观锁机制。
开启事务功能时(multi)
multi //开启
command1
command2
command3
command4
exec //提交
discard //取消,非回滚
4条语句作为一个组,并没有真正执行,而是被放入同一队列中。
如果,这是执行discard,会直接丢弃队列中所有的命令,而不是做回滚。
exec:当执行exec时,对列中所有操作,要么全成功要么全失败
127.0.0.1:6379> set a b
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set a b
QUEUED
127.0.0.1:6379> set c d
QUEUED
127.0.0.1:6379> exec
1) OK
2) OK
第七章 redis乐观锁实现(模拟买票)
发布一张票
set ticket 1
窗口1:
watch ticket
multi
set ticket 0 1---->0
窗口2:
multi
set ticket 0
exec
窗口1:
exec
第八章 服务器管理命令
#常用命令
Info //所有状态信息
info memory //查看内存情况
info repliaction //查看复制状态;新版本master-slave架构描述改为master-replica
CONFIG GET/SET //配置获取/修改
SHUTDOWN 关闭服务器
关闭数据库:
redis-cli -a root shutdown
Client list //客户端列表
Client kill ip:port //杀掉某一个会话,本地会话无法杀掉
config get * //查看所有配置信息
CONFIG RESETSTAT //重新统计配置信息
Dbsize //查看键值对个数
FLUSHALL //清空所有数据,危险,禁用
select 1 //切换1号库,默认在0号库;仅限单机,集群只能在0号库
FLUSHDB //清空当前库,危险,禁用
MONITOR //监控实时指令,可以作审计
redis-cli -a 123 -h 10.0.0.51 monitor > a.log & //后台监控10.0.0.51机器redis指令
网友评论