为什么Redsi能这么快:
- 完全基于内存,绝大部分请求是纯粹的内存操作,执行效率高
- 数据结构简单,对数据操作也简单
- 采用单线程(处理网络请求),单线程也能处理高并发请求,想多核也可以启动多个实例(多个rendis服务端)
- 使用多路I/O复用,非阻塞IO
Window版下载安装及启动:
- 下载安装
下载地址:https://github.com/MicrosoftArchive/redis/tags
选择zip下载:
下载后解压,可以看到一个是服务端,一个是客户端,如图:
- 启动
使用前必须先打开redis-server.exe。
再打开redis-cli.exe,然后才可以在redis-cli.exe打开的命令窗口编写相关的操作语句
Linux版下载安装及安装(ubuntu为例):
如果对linux的操作还不熟悉的可以参考:linux详细入门
在linux的命令行下载安装包: wget http://download.redis.io/releases/redis-4.0.11.tar.gz
解压安装包:tar -xvf redis-4.0.11.tar.gz
可以看到用户目录下有安装包文件也有解压后的文件
进入解压后的文件:cd redis-4.0.11
安装:make install(默认情况下是安装到redis-4.0.11目录下的src目录)
可以看到安装后多了一个src目录以及src目录下的安装文件如图:
至此安装完毕!
- 启动
方式一(不推荐):
在src目录下输入:redis-server,便能开启服务端
然后再打开一个终端输入redis-cli,开启客户端,之后便能够在该终端窗口输入相关的命令操作
方式二(推荐):
在/redis-4.0.11目录下输入:cat redis.conf | grep -v "#" | grep -v "^$" > redis-6379.conf
将配置文件中的注释行和空行去掉后追加redis-6379.conf
在/redis-4.0.11目录下输入:vim redis-6379.conf
编辑redis-6379.conf文件,编辑结果如图:
编辑完成后,保存并退出
如果需要开多个服务器,可以按照以上方法多配置几个文件,修改端口号,日志文件
随着配置文件的增加,如果一直放在/redis-4.0.11目录下,会导致该目录下的文件比较复杂
所以我们可以在/redis-4.0.11目录下创建一个文件夹conf,专门来存放配置文件
在conf目录下输入:redis-server redis-6379.conf(配置文件),便能启动服务
启动服务后,可以看到在conf目录下已经生成了日志文件
然后再打开一个终端,输入redis-cli -p 端口号,开启客户端,之后便能够在该终端窗口输入相关的命令操作
redis的基本操作:
- String 类型数据的基本操作:
- set key value
- get key
- mset key1 value1 key2 value2
- mget key1 key2
- strlen key :获取数据字符个数
- append key value :有得追加,无则创建
- incr key :默认增加1
- incrby key increment :增加整数
- incrbyfloat key increment : 增加浮点数
- decr key : 默认减少1
- decrby key increment :减少整数
- hash 类型数据的基本操作:
- hset key filed vaule
- hget key filed
- hmset key filed1 vaule1 filed2 vaule2
- hgetall key :获取所有的filed和value
- hkeys key :获取所有的 filed
- hvals key:获取所有的 value
- hincrby key field increment :增加整数
- hincrbyfloat key field increment :增加浮点数
- list类型数据(重复有序)的基本操作:
- lpush key value1 value2 value3:右添加
- rpush key value1 value2 value3:左添加
- lrange key start stop :获取一组数据
- lindex key index:获取某个数据
- llen key :获取长度
- lpop key:从左边移除一个数据
- rpop key:从右边移除一个数据
- lrem key count value :移除count个特定值
- blpop testlist second :如果在限定时间内,生产者有push内容testlist,那么消费者就能pop出来,否则返回nil(blpop只能供一个消费者使用)
- subscribe key :消费者订阅某个key,只要生产者publish key "xxxx",那么该消费者就能接收到“xxx”(subscribe可供多个消费者使用)
- set数据类型(不重复无序)的基本操作:
- sadd key number1 number2:添加数据
- smembers key:获取数据
- srem key number1 number2:删除数据
- scard key:获取集合数据总量
- sismember key member:判断集合中是否包含指定数据
- sinter key1 key2 :交集
- sunion key1 key2 :并集
- sdiff key1 key2 :差集
- sort_set类型数据的基本操作:
- zadd key score member1 score member2 :添加数据
- zrange key start stop withscores :从小到大排序(按索引)
- zrerange key start stop withscores:从大到小排序
- zrangebyscore key min max withscores:从小到大排序(按大小范围)
- zrangebyscore key max min withscores:从大到小排序
- zrem key member1 member2:删除数据
- zremrangebyrank key start stop:按索引删除数据
- zremrangebyscore key min max:按大小删除数据
- zcard key :获取数据总量
- zcount key min max:按大小范围获取数据总量
- zrank key member:从小到大排序后获取索引
- zrevrank key member :从大到小排序后获取索引
- zscore key member:按member查score
- zincrby key increment member:按照member对score增加increment
- key的通用操作:
- del key:删除指定key
- exists key :获取key是否存在
- type key :获取key的类型
- keys * :查询所有的key,*表示任意数量的任意字符
- keys ? : 查询一个字符的key,?表示匹配一个任意字符
- renamenx key newkey :为key改名
- scan cursor [match key] [count num]:SCAN命令是一个基于游标的迭代器, 这意味着命令每次被调用都需要使用上一次这个调用返回的游标作为该次调用的游标参数,以此来延续之前的迭代过程, 当SCAN命令的游标参数被设置为 0 时, 服务器将开始一次新的迭代, 而当服务器向用户返回值为 0 的游标时, 表示迭代已结束。key支持精准查询,也支持模糊查询,num规定的每次迭代返回的数量,这个数量只是一个大概范围,并不是每次都返回num个结果(考点)
- db的相关操作:
- select db :选择数据库
- move key db :将key移动到指定的库
redis的事务和锁:
- 事务
- multi:开启一个事务
- exec:执行事务
- discard:取消事务
- 锁
- watch key :监控一个key(开启事务之前先watch,只要监控到key发生改变,则所有的事务操作作废)
- 分布式锁
- setnx lock-key value:获得分布式锁(获得该锁后,其他客户端无法再获得)
- del lock-key:释放该分布式锁
- expire lock-key second :为该锁添加时间限定,到时自动释放(避免死锁)
- set lock-key value ex second nx:将1和3结合了起来,使得原子性得到满足 (考点)
redis的持久化:
- RDB(保存数据)
相关配置:
dbfilename dump.rdb:数据存放的文件名,通常设置为dump-端口号.rdb
dir:数据存放路径,如果不设置默认放在跟配置文件的同个目录下
rdbcompression yes:是否保存数据的文件进行压缩,默认为yes,采用LZF压缩
rdbchecksum yes:是否对保存数据的文件进行校验,该校验过程在写文件和读文件均进行
三种RDB启动方式:save指令,bgsave指令,save配置
save指令:
设置完数据后,手动输入save进行保存
保存完后返回服务端,查看保存数据的文件dump-6380.rdb
bgsave指令:
save指定有一个明显缺点就是save指令执行后,会加入到当前的进程队列,等待排队执行,如果save指令保存的数据非常多,必然会导致线程阻塞,而bgsave指令的出现就很好的解决了这一问题
首先设置完数据后,手动输入bgsave保存
它会调用fork函数生成子进程,开启另外一个进程来执行bgsave指令,很好的避免了阻塞问题
执行完后,回到服务器同样也能看到保存的数据
save配置:
前面两种启动方式都需要我们手动执行,实际操作中比较麻烦,所以就有了save配置,这是一种自动化的方式
首先我们在配置文件中进行如下配置,该指令表示在10秒内,只要有2个key发生变化就马上保存数据
- AOF(保存操作指令)
相关配置:
appendonly yes|no :是否开启AOF持久化功能,默认为不开启状态
appendfsync :always | everysec | no(always为每次,everysec每秒,no不可控)
appendfilename filename:保存操作指令的文件名,默认文件名为appendonly-端口号.aof
现在客户端执行一条指令
回到服务端,就可以看到生成的appendonly-6380.aof文件,该文件保存了这条操作指令
手动重写指令:bgrewriteaof
回到服务端,可以看到三条指令被合并了起来
- RDB vs AOF
持久化方式 | RDB | AOF |
存储空间 | 小(数量级:压缩) | 存储空间大(指令级别:重写) |
存储速度 | 慢 | 快 |
恢复速度 | 快 | 慢 |
数据安全性 | 会丢数据 | 依据策略决定 |
资源消耗 | 重量级 | 轻量级 |
启动优先级 | 低 | 高 |
redis的删除策略和逐出策略
过期数据:Redis是一种内存级数据库,所有数据均存放在内存中,内存中的数据可以通过TTL指令获取其状态,XX表示具有时效性的数据,-1表示永久性的数据,-2表示过期的数据或被删除的数据或未定义的数据
删除策略的目标:在内存占用与CPU之间寻找一种平衡,顾此失彼都会造成整体redis性能下降,甚至引发宕机和内存泄漏
删除策略:
- 定时删除:创建一个定时器,过期时间一到就删除,此删除方式节约内存但是CPU的负载量高
- 惰性删除:数据到达过期时间不做处理,等下次访问时再删除,此删除方式节约CPU性能,但内存压力大
- 定期删除:周期性轮询redis库中的时效性数据,算是定时删除和惰性删除的一种折中方案
逐出策略:如果内存不足,redis要临时删除一些数据为当前指令清理存储空间,这便是逐出策略
使用Pipeline的好处
- redis基于请求/相应模型,单个请求处理需要一一应答
- Pipeline批量执行命令,节省多次IO的往返时间
redis的同步机制
- 全同步过程
- Salve发送sync命令到Master
- Master启动一个后台进程,将Redis中的数据快照保存到文件中
- Master将保存数据快照期间接收到的写命令缓存起来
- Master完成写文件操作后,将该文件发送给Salve
- Slave接收到数据后,就进行数据的恢复
- Master将这期间收集到的增量写命令发送给Salve端
- 增量同步
- Master发送复制缓冲区信息
- Slave接收信息,执行bgrewriteaof,恢复数据
redis Sentinel(哨兵)
哨兵的出现是为了解决主从同步Master宕机后的主从切换问题
监控:检查主从服务器是否运行正常
提醒:通过API向管理员或者其他应用程序发送故障通知
自动故障迁移:主从切换
redis的集群
如何从海量数据里快速找到所需?
分片:通过一致性哈希算法,将哈希值空间组织成虚拟的圆环,分散存储在多个节点(集群)上。这样做的好处就是,在增加服务器和删除服务器的时候,受影响的仅仅是相邻的两台服务器,其他服务器并不会收到影响。如果采用普通的哈希算法,在增加和删除服务器的时候,受影响的是整个集群
关于雪崩,击穿,穿透
雪崩:在一个较短的时间内,缓存中较多的key集中过期,在此周期内请求访问过期的数据,redis未命中,redis向数据库获取数据,数据库同时接收到大量的请求无法及时处理,redis大量请求被积压,开始出现超时现象,数据库流量激增,数据库崩溃,数据库重启后仍然面对缓存中无数据可用,redis服务器资源被严重占用,Redis数据库奔溃,Redis集群呈现崩塌,集群瓦解,应用服务器无法及时得到数据相应请求,来及客户端的请求数量越来越多,应用服务器奔溃,最终导致应用服务器,数据库,redis全部重启呈现雪崩想象
解决雪崩:
1.更多的页面静态化处理
2.构建更多的缓存架构
3.对mysql严重耗时的业务进行排查
4.限流
击穿:redis中某个key过期,该key的访问量巨大,多个数据请求从服务器直接压到Redis后,均未命中,Redis在短时间内发起大量对数据库中同一数据的访问
解决方案:
1.加大此类信息key的过期时长
2.现场调整,对自然流量激增的数据延长过期或者设置为永久性key
穿透:redis中大面积出现未命中,出现了非正常URL访问,获取的数据在数据库中也不存在,数据库查询未能够得到对应数据。出现此类想象可能是出现了黑客攻击
解决方案:
1.白名单策略:加载异常数据直接拦截
2.实时监控redis的命中率与null数据的占比,根据比率选择性过滤