1.什么是redis
- redis是一个使用c语言编写的数据库
- redis和MongoDB一样事属于nosql类型的数据
2.redis的特点
-
速度快 redis默认情况下将数据储存在内存中读取速度能达到10万/s左右,写入能达到8万次/s左右有
-
支持数据的持久化
redis 默认情况将数据存在内存中,但是也可以将内存中的数据源保存在磁盘中
-
支持多种数据结构
redis是通过key-value形式储存数据的,value不仅支持常见的字符串类型,整型以外,同时还提供了list,set,zset,hash等数据结构的储存
-
定制型强
redis虽然强大,但是它还是开源免费的
-
支持分布式
和MongoDB一样,redis是支持主从复制,支持分布式储存的
redis场景应用
-
缓存系统
由于redis是将数据储存在内存中的,所以我们可以使用redis来实现内存缓存,对于经常会被查询,但是不经常修改或者删除的数据,储存到redis中如:
排行榜:
由于redis支持集合(set)和有序集合(sorted set)所以我们在实现排行榜的时候变的非常简单
计数器:
由于redis提供了incr/decr指令,使得我们在实现计数器时变的非常简单
转发数/评论数/播放数/访问数...
储存社交关系
由于redis支持储存集合类型数据,由于社交关系不会经常发生变化,所以很多社交网站会使用redis来储存社交关系,如:微博的共同关注好友等
1.Redis下载和安装
全程下一步
redis.windows.conf: 配置文件,将redis作为普通软件使用的配置,命令行关闭则redis关闭
redis.windows-service.conf:配置文件,将redis作为系统服务的配置,用以区别开两种不同的使用方式
1.配置文件修改
redis.windows-service.conf
- 绑定IP
bind 127.0.0.1
- 绑定端口号
port 6379
- 数据库文件
dbfilename dump.rdb
- 数据文件存储路径
dir ./
- 默认数据库
databases 16
- 日志文件
logfile "server_log.txt"
- 主从复制(类似于双机备份)
slaveof
-->
redis数据类型
1.redis数据类型
redis是以key-value的形式储存数据的,key无论 如何都是以字符串类型,value支持以下5中类型:
1.字符串(string)
2.哈希(hash)
3.列表(list)
4.无序集合(sets)
5.有序集合(sorted sets)
-
string (字符串)
格式:key value
示例 :name zhangsan
-
hash(哈希)
格式:key field value
示例:
user name ljn
user age 18
user gender man
hash就相当于编程中的Map或者对象
注意点:hash 是无序的
-
list(列表)
list就相当于编程开发中的链表或者数组
格式:key value1 value2 value3 。。。
示例:name lnj zs ls ww ...
注意点list是有序的
-
set (集合)
键是string ,值是set
一堆无序的数据
注意点:储存的数据不能重复
-
zset(有序集合)
一堆有序的数据,通过权重和实现排序
注意点:储存的数据不能重复
string操作类型
1.默认数据库
默认情况下redis 给我们创建了16个数据库(0-15)如果使用的时候没有明确选中使用哪个数据库,那么默认使用第0个数据库
2.切换数据库
select 1
3.字符串类型-增删改查
redisdoc.com 所有语法文档
-
新增
set key value
set name ljn
-
查询
get key
set name
-
修改
set key value
如果值存在就是修改,不然就是新增
-
删除
del key
del name
4.字符串的高级设置
-
set key value
不管key是否存在都在设置,存在就是修改,不存在就是新增
-
setnx key value
只有 key 不存在的时候才新增
-
set key value xx
xx表示只有key存在才设置(修改)
5.字符串类型批量设置
-
批量添加
mset key value key value
mset name lnj age 18
-
批量查询值
mget key key key
mget name age
6.字符串的其他操作
-
设置新值返回旧值
getset key newvalue
-
给旧值追加数据
append key value
-
计算value字符串长度
strlen key
注意点:中文问题
-
获取指定下标范围的值
getrange key start end
-
从指定下标开始设置字符串的值
setrange key offset value
7.字符串类型-自增-自减操作
-
incr
作用:给指定key 的对应value自增1,key如果不存在会自动新增,并从0开始自增1
格式:incr key
-
decr
作用:指定key的对应value自减1,如果key不存在就会自动新增,并从0开始自减1
格式:decr key
-
incrby
作用:给指定key的对应的value增加指定的值,如果key不存在就会自动新增,并从0开始增加
格式:incrby key number
-
decrby
作用:给指定key的对应value减少指定的值,如果key不存在就会自动新增,并从0开始自减
格式:decrby key number
-
incrbyfloat
作用:给指定key的对应value 增加指定的值,key如果不存在会自动新增,并从0开始自增
格式:incrbyfloat key value
8.通用查询命令
-
查询当前数据库中所有key
key *
-
清空所有数据库(离职操作)
flushall
-
清空当前数据库
flushdb
注意点:由于redis是单线程的,而以上操作都是非常耗时的,所以不推荐在企业开发中使用
-
计算当前数据库中所有key的总数
dbsize
注意点:dbsize并不是通过遍历统计得到当前数据库中的key的总和,而是每次操作时内部都会自动统计所以dbsize并不是一个耗时的操作
-
查看value数据类型
type key
-
判断指定key是否存在
exists key
如果存在返回1不存在返回0
-
设置key过期时间
expire key seconds
注意点:如果没有添加过期时间就是添加,如果有就是修改过期时间
-
查看过期时间
ttl key
-
取消过期时间
persist key
注意点:如果key不存在或者已经被删除会返回-2,如果存在并且过期时间已经被删除会返回-1
redis 哈希类型操作符
1.redis-hash类型-增删改查
redis的value除了可以储存普通的字符串类型以外,还可以储存hash类型hash类型就相当于在js中的对象,可以把整个对象当做一个value储存起来
-
增加
hset key field value
hset user name it666
hset uset age 23
-
查询
hget key field
hget user name
-
修改
如果字段不存在就新增,如果字段存在就修改
hset key field value
hset user name Leo
-
删除
删除指定字段
hdel key field
hdel user name
删除对应可以所有的数据
del key
del user
2.redis -hash -高级操作
-
批量查询
hmget key field1 field2 field3
hmget user name age score
-
工具指令
hlen key 返回key粗存的hash表中有多少数据
hlen user
hexists key field 判断指定的key储存的hash中是否有指定的字段
hexists user name 返回1表示存在 0表示不存在
3.redis-hash 类型的其他操作
-
查询所有的value
hvals key
hvals user
-
查询所有的field
hkeys key
hleys user
-
查询所有的field和value
hgetall key
hgetall uset
注意点:由于redis 是单线程的,而以上操作时非常耗时的所以不推荐在企业开发中使用
redis-list 类型
1.redis -list 增删改查
redis的value除了可以储存字符串和hash类型以外,还可以储存list类型,list就相当于js中的数组,可以把整个数组当作一个value储存起来
注意:list是有序的
-
增加
从第二个value开始会添加到前一个的左边
lpush key value1 value2 value3
lpush arr1 aa bb cc ==> cc bb aa
从第二份value开始会添加到前一个的右边
rpush key value1 value2 value3
rpush arr1 aa bb cc ==> aa bb cc
-
查询
查询指定的数据范围数据
lrange key starindex endindex
索引从 0开始,endindx等于-1表示取到最后
-
查询指定索引数据源
lindex key index
从后往前索引从0开始,从后往前索引从-1开始
-
修改
lset key index value
注意index是从0开始
-
删除
lpop删除左边元素
lpop key
rpop 删除 右边元素
rpop key
-
lrem删除指定个数的指定元素
lrem key count value
count >0 表示从表头开始向表尾搜索,移除与value相等的元素,数量为count
count <0 表示从表尾开始向表搜索,移除与value相等的元素,数量为count的绝对值
couont=0 表示移除表中所有与value相等的值
-
ltrim按照索引剪切列表
ltrim key start end
2.redis-list类型 其他操作
-
追加数据
lpush key value1, value2
rpush key value1, value2
-
插入数据
linsert key before| after oldvalue newvalue
-
获取列表长度
lien key
-
列表实现简单数据结构
栈结构(水桶)- 先进后出
lpush lpop
-
队列结构(水管)-先进先出
rpush rpop
所以在企业中如果需要先进先出或者先进后出的数据我们就可以将这些数据储存在list列表中
redis -set 类型操作
集合就是一堆无序的数据,redis可以把一堆无序的数据当做value储存起
注意点:集合中不能出现重复的数据
1.redis set 增删改查
-
新增
sadd key value1,value2
-
查询
返回集合中所有元素
smembers key
注意点:由于redis是单线程的,而以上操作时非常耗时的,所以当元素比较多时,需要谨慎使用
返回集合中N个元素
srandmember key [count]
-
删除
-
随机删除n个元素
spop key
-
删除集合指定元素
srem key value1 ,[value2,...]
2.redis-set 其他操作
-
追加元素
sadd key 不存在就增加存在就追加
-
统计集合的个数
scard key
-
判断集合中元素的个数
scard key
-
判断集合中是否有指定元素
sismember key member
3.redis中的集合是支持集合间的操作,也就是并集,交集和差集
-
交集
sinter key [key ,...]
{1,2,3}n {2,3,4}={2,3}
-
并集
sunion key [key,...]
{1,2,3}n {2,3,4}={1,2,3,4}
-
差集
sdiff key [key,...]
{1,2,3}n {2,3,4}={1}
{2,3,4}n{1,2,3}={4}
-
redis-set类型操作应用场景
抽奖
sismember key [count]
社交关系
sinter key [key ,...]
redis ZSet
1.什么事ZSet
ZSet是有序集合,redis可以把一堆通过权重排序的数据当做一个value储存起来
2.Redis-ZSet类型操作-曾删改查
-
新增
zadd key 权重 value 权重 value
-
查询
查询指定排名范围内的数据
zrange key start end
查询指定权重范围内的数据
zrangebyscore key 权重 权重
查询指定元素权重
zscore key element
查询指定权重范围内元素个数
zcount key minscore maxscore
查询集合中元素个数
zcard key
-
删除
删除指定元素
zrem key value
删除指定排名范围元素
zremrangbyrank key start end
删除指定权重范围元素
zremrnagbrscore key minscore maxscore
3.ZSet类型的其他操作
-
增加或者减少元素权重
zincrby key score element
-
redis-zset 应用场景
储存排行榜数据
node中连接redis
// 1.导入Redis库
const redis = require("redis");
// 2.利用这个库连接到Redis服务器
const client = redis.createClient('6379', '127.0.0.1');
// 3.监听连接成功还是失败
client.on("error", function(error) {
console.error(error);
});
// 4.通过连接对象操作Redis
// client.set('name', 'lnj', redis.print);
// client.get('name', (err, val)=>{
// if(err){
// console.log(err);
// return
// }
// console.log(val);
// });
client.hset('user', ['name', 'zs'], redis.print);
client.hget('user', 'name', (err, val)=>{
if(err){
console.log(err);
return
}
console.log(val);
});
redis持久化
1.redis数据持久化
- 默认情况下redis是将数据保存在内存中,保存在内存中的数据有一个特点,那就是机器重启之后数据就会丢失,所以为了避免服务器重启死机问题发生,redis中保存数据的丢失,redis提供了数据持久化功能
2.什么事数据持久化
-
数据持久化就是将内存中的数据写入到磁盘中redis和大部分主流数据库(MySQL、MongoDB)一样,支持RDB和AOF持久化
RDB(快照)
将内存中所有内容写入到一个文件中
出发生产rdb的三种机制
同步执行
如果已经存在就得rdb文件中,会利用新的覆盖旧的,手动执行bgsave命令
异步执行
如果已经存在旧的rgd文件,会利用新的覆盖旧的
通过配置文件自动生成
通过配置文件指定自动生成的条件,一旦满足条件就会自动执行bgsave生成rdb文件
dir ./ #RDB文件保存的路径
dbfilename dump.rdb #RDB文件的名称
#save 900 1 #自动生成条件
#save 300 10
#save 60 10000
stop-writes-on-bgsave-error yes #bgsave发生错误是否停止写入
rdbcompression yes #是否采用压缩模式写入
rdbchecksum yes #是否对生成的RDB文件进行校验
1.AOF(日志)
将每一条操作Redis的指令都写入到文件中
2.触发生成AOF三种机制
- always
-
每条命令都写入一条命令到文件中
-
优点: 不会丢失数据
-
缺点: 磁盘I/O消耗较大
- everysec
-
每隔1秒写入一次, 也就是先收集1秒钟的命令, 然后再一次性写入到文件中
-
优点: 磁盘I/O消耗相对较小
-
缺点: 可能丢失1秒数据
- no
-
让操作系统决定什么时候写入, 操作系统想什么时候写入就什么时候写入
-
不可控, 可能丢失大量数据
1.AOF文件重写
-
随着时间的推移AOF文件会越来越大
-
文件越来越大带来的问题就是-磁盘消耗越来越大
-
文件越来越大带来的问题就是-写入速度会越来越慢
-
文件越来越大带来的问题就是-恢复的时间越来越慢
-
... ...
-
所以AOF提供了重写的机制
-
我们可以对AOF文件中保存的内容进行优化
-
从而降低文件的体积
-
从而提升文件的恢复速度
-
在AOF的重写机制中
-
可以将自动去除冗余命令
-
可以自动删除没有用的命令
-
... ...
-
例如:
-
优化前: set name lnj; set name zs; set name ls;
-
优化后: set name ls;
-
优化前: incr count; incr count; incr count; incr count;
-
优化后: set count 4;
-
优化前: expire name 3
-
优化后: 3秒后由于数据已经被删除, 所以这条命令不用保存
-
... ...
2.触发AOF重写两种机制
- bgrewriteaof命令
- 开启一个新的子进程, 根据内容中的数据生成命令写入到AOF文件中
- 配置文件设置
auto-aof-rewrite-min-size 200mb #AOF文件体积达到多大时进行重写
auto-aof-rewrite-percentage 100 #对比上一次重写后, 增长了百分之多少再次进行重写
#例如上一次重写后大小是100MB, 如果设置为50, 那么下一次就是增长0.5倍(150M)之后再重写
#例如上一次重写后大小是100MB, 如果设置为100, 那么下一次就是增长两倍(200M)之后再重写
- AOF推荐配置
appendonly yes #是否使用AOF
appendfilename "appendonly-${prot}.aof" #AOF文件名称
appendfsync everysec #写入命令的同步机制
dir /rdbdiskpath #保存AOF文件路径
auto-aof-rewrite-min-size 64mb #AOF文件重写体积
auto-aof-rewrite-percentage 100 #AOF文件增长率
no-appendfsync-on-rewrite yes #AOF重写时是否正常写入当前操作的命令
1.RDB和AOF对比
- AOF优先级高于RDB
- 如果Redis服务器同时开启了RDB和AOF, 那么宕机重启之后会优先从AOF中恢复数据
- RDB体积小于AOF
- 由于RDB在备份的时候会对数据进行压缩, 而AOF是逐条保存命令, 所以RDB体积比AOF小
- RDB恢复速度比AOF恢复速度快
- 由于AOF是通过逐条执行命令的方式恢复数据, 而RDB是通过加载预先保存的数据恢复数据
所以RDB的恢复速度比AOF快
- AOF数据安全性高于RDB
- 由于AOF可以逐条写入命令, 而RDB只能定期备份数据, 所以AOF数据安全性高于RDB
- 所以综上所述, 两者各有所长, 两者不是替代关系而是互补关系
1.Redis高可用性
- 如果所有用户都从同一台Redis服务器上读写数据
那么如果这台Redis服务器宕机了, 用户就不能进行读写了
- 如果我们有多台Redis服务器, 并且每台服务器中存储的内容都相同
那么即使有一台服务器宕机了, 用户还可以继续使用其它的服务器
- 以上这种特点, 我们就称之为'高可用性'
2.Redis数据安全性
- 如果所有数据都保存在同一台Redis服务器上
那么如果这台Redis服务器坏了, 那么很有可能会导致数据丢失
- 如果我们有多台Redis服务器, 并且每台服务器中存储的内容都相同
那么即使有一台服务器坏了, 也不会导致数据丢失
因为我们还有其它保存了相同内容的服务器
- 以上这种特点, 我们就称之为'数据的安全性'
3.Redis数据分流
- 如果所有用户都从同一台Redis服务器上读写数据
那么由于服务器的性能限制和网络传输速度的限制
如果同一时刻用户量较多时, 服务器负荷增大, 数据处理速度变慢的问题
- 如果我们有多台Redis服务器, 如果我们把请求分流到不同的服务器
那么就可以降低了服务器压力, 加快数据处理速度
并且如果我们将多台服务器安装到不同的区域, 还可以采用就近原则访问
还可以进一步提升用户的访问速度
- 以上这种特点, 我们就称之为'数据分流'
4.Redis主从复制
- 主从复制就是使用多台保存了相同内容的Redis服务器来组成一个数据库集群
这个数据库集群中的每一台Redis服务我们称之为一个节点
5.Redis主从复制特点
- 主从复制中必须有一个主节点
- 主节点主要负责写入数据和读取
- 主从复制中除了主节点以外的节点我们称之为'从节点'
-
副节点默认情况下只能读取数据, 不能写入数据
-
副节点主要负责从主节点不断复制数据
- 和MongoDB不同的是,Redis中的主从复制, 主节点挂掉后不会自动选举
如果需要自动选举需要借助Redis Sentinel来实现
1.搭建Redis主从复制
1.1拷贝多份Redis安装包
1.2修改主节点配置
bind 127.0.0.1 #绑定ip地址
port 6380 #绑定端口号
dir ./ #RDB文件存储路径
dbfilename dump-${prot}.rdb #RDB文件名称
stop-writes-on-bgsave-error yes #bgsave遇到错误是否停止
rdbcompression yes #是否压缩RDB文件
rdbchecksum yes #是否校验RDB文件
#save 900 1
#save 300 10
#save 60 10000
appendonly yes #是否使用AOF
appendfilename "appendonly-${prot}.aof" #AOF文件名称
appendfsync everysec #写入命令的同步机制
dir /rdbdiskpath #保存AOF文件路径
auto-aof-rewrite-min-size 64mb #AOF文件重写体积
auto-aof-rewrite-percentage 100 #AOF文件增长率
no-appendfsync-on-rewrite yes #AOF重写时是否正常写入当前操作的命令
logfile "${prot}_log.txt" #系统日志文件名称
1.3修改从节点配置
port 6381 #绑定端口号
slaveof 127.0.0.1 6380 #主节点地址和端口
port 6382 #绑定端口号
slaveof 127.0.0.1 6380 #主节点地址和端口
1.4注册启动Redis服务
命令行进入安装包路径下, 执行如下指令
redis-server.exe --service-install redis.windows-service.conf --service-name Redis6380
redis-server.exe --service-install redis.windows-service.conf --service-name Redis6381
redis-server.exe --service-install redis.windows-service.conf --service-name Redis6382
1.5查看主从状态
redis-cli -h 1270.0.01 -p 6380
info replication
redis-cli -h 1270.0.01 -p 6381
info replication
1.6测试主从复制
1.主从复制原理
1.初始化同步(全量复制)
-
给一个从节点添加主节点之后, 从节点会给主节点发送全量复制请求
-
主节点收到全量复制请求, 会执行bgsave生成RDB文件
-
主节点生成完RDB文件, 会将RDB文件发送给从节点
2.同步写库记录(部分复制)
2.1初始化同步
- 主节点在生成和发送RDB过程中, 如果还收到了其它的命令
Redis会存储到缓冲区中
-
当RDB文件发送完毕之后, 会将缓冲区中的缓存的命令发送给从节点
-
从节点收到RDB文件,收到缓冲区命令后, 会先清空自身保存的数据
然后加载RDB文件中的内容, 然后执行收到的其它命令
2.2后续同步
- 主节点每执行一个写命令就会向从节点发送相同的写命令
从节点接收到主节点发送过来的命令, 就执行对应的命令
以实现和主节点同步
1.主从复制存在的问题
- 主从复制有效的解决了Redis'数据安全性'和'数据分流的问题'
但是Redis主从复制并没有解决'高可用性'的问题
- 在标准的主从复制中只有主节点可以读写数据, 从节点只能读取数据
所以一旦主节点宕机了, 那么用户就不能继续写入数据了
- 也就是说在Redis的主从复制中, 主节点宕机了, 系统是不会自动重新选举一个主节点出来的
2.Redis-Sentinel
-
Redis-Sentinel是一个用来监控主从结构中每个节点的状态
-
我们可以给Redis-Sentinel添加多个Sentinel节点, 让这些节点来监控主从结构的状态
-
一旦发现主节点挂掉了, 再让这些Sentinel节点帮我们重新从从节点中选举出一个主节点
3.Redis-Sentinel是如何做到高可用的?
- Redis-Sentinel有三个定时任务
-
一个用于获取主从关系,发现新节点
-
一个用于交换信息,投票选出新主服务器
-
一个用于监听节点是否可用
- 每10秒每个sentinel节点对master节点和slave节点执行info操作
-
确定主从关系
-
发现子节点
- 每2秒每个sentinel节点通过master节点的channel(sentinel:hello)交换信息
- 目的就是为故障判断,信息交互提供通道
- 每1秒每个sentintel节点对master节点和slave节点以及其余的sentinel节点执行ping操作
- 心跳检测节点是否发生故障
-->