## 基础
redis是可基于内存亦可持久化的日志型、Key-Value数据库.
类似于memcached,但是支持更复杂的数据结构List、Set、Sorted Set等,并且有持久化的功能
### 特性
1. 单进程单线程模型,redis利用队列技术将并发访问变为串行访问,消除了传统数据库串行控制的开销
2. 操作具有原子性
3. 其数据库完全保存在内存中,仅使用磁盘进行持久化
4. 丰富的数据类型
5. 支持分布式,可以将数据复制到任意数量的从机(slave)中
6. 支持事务
单个步骤处理一组命令,原子意味着要么处理所有命令,要么都不处理
命令序列化,按顺序执行
原子性
三阶段: 开始事务 - 命令入队 - 执行事务 - 取消事务
命令:MULTI/EXEC/DISCARD
7. 发布订阅
Pub/sub是一种消息通讯模式
Pub发送消息, Sub接受消息
Redis客户端可以订阅任意数量的频道
“fire and forgot”, 发送即遗忘
命令:Publish/Subscribe/Psubscribe/UnSub
Redis发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。Redis 发布订阅(pub/sub)实现了消息系统,发送者(在redis术语中称为发布者)在接收者(订阅者)接收消息时发送消息。传送消息的链路称为信道。
在Redis中,客户端可以订阅任意数量的信道
8. key监视
UNWATCH
取消 WATCH 命令对所有 key 的监视。
WATCH key [key ...]
监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。
### 应用场景
1. 缓存系统(“热点”数据:高频读、低频写)
后台先从缓存中取数据,取到直接返回结果,取不到时从数据库中取,数据库取到更新缓存,并返回结果,数据库也没取到,那直接返回空结果
2. 计数器
组合使用 INCR 和 EXPIRE ,来达到只在规定的生存时间内进行计数(counting)的目的.
例如防止刷单:一个接口请求,限制每秒请求总数为200次,超过200次就等待,等下一秒,再次请求
3. 消息队列系统(list、pub/sub)
redis自带的list类型(lpush和rpop或者brpop,rpush和lpop或者blpop)---blpop和brpop是阻塞读取。
"发布/订阅"模式(publish channel message 和 subscribe channel [channel ...] 或者 psubscribe pattern [pattern ...] 通配符订阅多个频道)
4. 排行榜 zset (设置key的过期时间,然后定时做统计)
zadd zscore zrevrange(按名次查看排行榜) zrevrank zrem zincrby del
分数中键入时间戳,解决相同时间的问题
5. 社交网络 set
点赞、踩、关注/被关注、共同好友等是社交网站的基本功能。redis封装了多个集合的交集、并集、差集
### 基本数据结构
1. String: 字符串
它不仅能够存储字符串、还能存储图片、视频等多种类型, 最大长度支持512M
一个key只能对应一个value。这里的key和value都是byte数组
GET/MGET
SET/SETEX/MSET/MSETNX
INCR/DECR
GETSET
DEL
2. Hash: 哈希(字典)
该类型是由field和关联的value组成的map。其中,field和value都是字符串类型的, 字符段字段和字符串值之间的映射,只要用于表示对象
redis中每个Hash可以存储 2^{32}-1个键值对(40多亿)
hset和hget命令分别为设置和获取某个key的键值对(field-value),hmset和hmget命令分别为设置和获取某个key的多个键值对,hgetall命令为获取某个key的全部键值对,hdel命令为删除某个key的键值对
HGET/HMGET/HGETALL
HSET/HMSET/HSETNX
HEXISTS/HLEN
HKEYS/HDEL
HVALS
1. List: 列表
一个插入顺序排序的字符串元素集合, 基于双链表实现. 双端链表和压缩列表.
一个列表最多可以包含2^{32}-1个元素
LPUSH/LPUSHX/LPOP/RPUSH/RPUSHX/RPOP/LINSERT/LSET
LINDEX/LRANGE
LLEN/LTRIM
1. Set: 集合
字符串的无序集合, 它和List类型最大的区别是:集合中的元素没有顺序, 且元素是唯一的.
集合中最大的成员数为2^{32}-1
Set是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)
Set类型主要应用于:在某些场景,如社交场景中,通过交集、并集和差集运算,通过Set类型可以非常方便地查找共同好友、共同关注和共同偏好等社交关系。
SADD/SPOP/SMOVE/SCARD
SINTER/SDIFF/SDIFFSTORE/SUNION
1. Sorted Set: 有序集合
ZSet是一种有序集合类型,每个元素都会关联一个double类型的分数权值,通过这个权值来为集合中的成员进行从小到大的排序。与Set类型一样,其底层也是通过哈希表实现的
ZADD/ZPOP/ZMOVE/ZCARD/ZCOUNT
ZINTER/ZDIFF/ZDIFFSTORE/ZUNION
## redis协议
redis 客户端和服务端之间通信的协议是RESP(Redis Serialization Protocol)。传输层使用TCP.
具有实现容易、易读、解析快的特点
RESP是支持的如下数据类型的文本序列换协议:
简单字符串(Simple Strings),错误(Errors),整数(Integers),批量字符串(Bulk String)和数组(Arrays)
在RESP中,协议的不同部分始终以“\ r \ n”(CRLF)结束
### 数据类型
在RESP中,某些数据的类型取决于第一个字节:
1. 对于简单字符串,回复的第一个字节是“+”
2. 对于错误,回复的第一个字节是“ - ”
3. 对于整数,回复的第一个字节是“:”
4. 对于批量字符串,回复的第一个字节是“$”
5. 对于数组,回复的第一个字节是“ *”
### 请求回复格式
#### 请求
*<number of arguments> :字符串的个数
$<number of bytes of argument N> :第N个字符串的长度
<argument data> :字符串值
数组的长度是3,第1个字符串是3字节的字符串内容是set 第2个是长度为5的字符串key11
```
*3
$3
set
$5
key11
$7
value11
```
#### 回复
1. 简答字符串
+ok\r\n
2. 错误
-Error message\r\n
3. 整数
:1000\r\n
4. 批量字符串
$6\r\nnf00bar\r\n
5. 数组
*2\r\n$3\r\nabc\r\n$4\r\nfeng\r\n
## 备份恢复
redis使用命令备份恢复当前数据库, 备份:SAVE BGSAVE 会生成dump.rdb
恢复将dump.rdb 放到安装目录启动redis
## 管道技术
Redis 管道技术可以在服务端未响应时,客户端可以继续向服务端发送请求,并最终一次性读取所有服务端的响应
## 持久化的方式
## 快照
缺省情况情况下,Redis把数据快照存放在磁盘上的二进制文件中,文件名为dump.rdb。你可以配置Redis的持久化策略,例如数据集中每N秒钟有超过M次更新,就将数据写入磁盘;或者你可以手工调用命令SAVE或BGSAVE。
工作原理
1. Redis forks.
2. 子进程开始将数据写到临时RDB文件中。
3. 当子进程完成写RDB文件,用新文件替换老文件
## AOF (APPEND ONLY MODE)
快照模式并不十分健壮,当系统停止,或者无意中Redis被kill掉,最后写入Redis的数据就会丢失.
的出现是为了弥补RDB的不足(数据的不一致性),采用日志的形式来记录每个写操作,并追加到文件中。Redis 重启的会根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。
打开 redis.conf 文件,找到 APPEND ONLY MODE 对应内容
1. redis 默认关闭,开启需要手动把no改为yes
appendonly yes
2. 指定本地数据库文件名,默认值为 appendonly.aof
appendfilename "appendonly.aof"
3. 指定更新日志条件
```
appendfsync always
appendfsync everysec
appendfsync no
``
解说:
always:同步持久化,每次发生数据变化会立刻写入到磁盘中。性能较差当数据完整性比较好(慢,安全)
everysec:出厂默认推荐,每秒异步记录一次(默认值)
no:不同步
4. 配置重写触发机制(当AOF文件的大小超过所设定的阈值时,Redis就会对AOF文件的内容压缩,解决aof文件过大)
```
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
``
解说:当AOF文件大小是上次rewrite后大小的一倍且文件大于64M时触发。一般都设置为3G,64M太小了。
1. redis 默认开启RDB持久化方式,在指定的时间间隔内,执行指定次数的写操作,则将内存中的数据写入到磁盘中。
2. RDB 持久化适合大规模的数据恢复但它的数据一致性和完整性较差。
3. Redis 需要手动开启AOF持久化方式,默认是每秒将写操作日志追加到AOF文件中。
4. AOF 的数据完整性比RDB高,但记录内容多了,会影响数据恢复的效率。
5. Redis 针对 AOF文件大的问题,提供重写的瘦身机制。
6. 若只打算用Redis 做缓存,可以关闭持久化。
7. 若打算使用Redis 的持久化。建议RDB和AOF都开启。其实RDB更适合做数据的备份,留一后手。AOF出问题了,还有RDB。
## 常见问题
### 内存满了怎么办
redis.conf配置文件中添加以下配置设置内存大小`maxmemory 100mb`
Redis支持运行时通过命令动态修改内存大小` config set maxmemory 100mb`
Redis定义了几种策略用来处理这种情况:
所有key或者设置了过期时间的key使用LRU最近最少使用淘汰或者随机淘汰;设置过期时间的key根据过期时间淘汰.
1. noeviction(默认策略):对于写请求不再提供服务,直接返回错误
2. allkeys-lru:从所有key中使用LRU算法进行淘汰
3. volatile-lru:从设置了过期时间的key中使用LRU算法进行淘汰
4. allkeys-random:从所有key中随机淘汰数据
5. volatile-random:从设置了过期时间的key中随机淘汰
6. volatile-ttl:在设置了过期时间的key中,根据key的过期时间进行淘汰,越早过期的越优先被淘汰
当使用volatile-lru、volatile-random、volatile-ttl这三种策略时,如果没有key可以被淘汰,则和noeviction一样返回错误
可以设置淘汰策略:maxmemory-policy allkeys-lru
LRU(Least Recently Used),即最近最少使用,是一种缓存置换算法
### 穿透
缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求,导致数据库压力过大
规避方案:
可能为攻击,接口层增加校验,如用户鉴权校验. 设置key-null,过期时间设置短一点儿
### 击穿
在Redis获取某一key时, 由于key不存在, 而必须向DB发起一次请求的行为, 引起数据库压力瞬间增大,造成过大压力,称为“Redis击穿”。
第一次访问; 恶意访问不存在的key; Key过期
规避方案:
服务器启动时, 提前写入
规范key的命名, 通过中间件拦截
设置热点数据永远不过期
### 雪崩
缓存雪崩是指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机。
和缓存击穿不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。
规避方案:
使用Redis集群
缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生
设置热点数据永远不过期
## 其他nosql
Memcache:这是一个和Redis非常相似的数据库,但是它的数据类型没有Redis丰富。作为一套分布式的高速缓存系统,对于一些大型的、需要频繁访问数据库的系统访问速度的提升效果十分显著
MongoDB:是一个基于分布式文件存储、面向文档的NoSQL数据库。介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系型数据库的,它支持的数据结构非常松散,是一种类似json的BSON格式。
有疑问加站长微信联系(非本文作者))