Redis
REmote DIctionary Server(Redis) 是一个由 Salvatore Sanfilippo 写的 key-value 存储系统,是跨平台的非关系型数据库
Redis 是一个开源的使用 ANSI C 语言编写、遵守 BSD 协议、支持网络、可基于内存、分布式、可选持久性的键值对(Key-Value)存储数据库,并提供多种语言的 API
Redis 通常被称为数据结构服务器
Redis 数据类型
Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)
数据类型 | 数据类型存储的值 | 说明 |
---|---|---|
String(字符串) | 字符串、整数、浮点数 | 字符串增加;求子串 整数、浮点数 计算自增… |
List(列表) | 链表、每个节点都含有一个字符串 | 支持 链表头尾 插入弹出 偏移剪切 查询、删除 指定节点 |
Set(集合) | 集合中的每个元素都是一个字符串,且他们都是唯一的 | 可 增删查 元素,检测元素是否存在集合 计算集合 交、并、差集 等 随机读取元素 |
Hash(哈希散列表) | Java中的 Map类 ,<K , V> | 可 增删改查 键值对可获取所有键值对 |
Zset(有序集合) | 有序集合,可能包含 字符串、整数、浮点数、分值(score)、元素(排列有分值大小决定) | 可 增删改查 元素 根据分值范围或成员 获取对应元素 |
HyperLogLog(基数) | 计算重复的值,确定存储数量 | 只提供基数运算,不提供返回功能 |
Redis 常用命令
Redis 命令用于在 redis 服务上执行操作
基本类型操作
说明 | 命令 |
---|---|
赋值 | SET key value |
取值 | GET key |
多键值赋值 | MSET key value [key value …] |
多取值 | MGET key [key …] |
字符串数值操作 | |
递增+1 | INCR key |
递减-1 | DECR key |
指定增加 | INCRBY key increment |
指定减少 | DECRBY key decrem |
Hash散列 | |
Hash赋值 | HSET key field value |
Hash取值 | HGET key field |
Hash多赋值 | HMSET key field value [field value] |
获取所有字段值 | HGETALL key |
List队列 | |
列表左增 | LPUSH key value [value …] |
列表左弹 | LPOP key |
列表右增 | RPUSH key value [value …] |
列表右弹 | RPOP key |
列表总数 | LLEN key |
查列表 | LRANGE key start stop |
Set集合(无序不可重复) | |
添加元素 | SADD key member [menber …] |
删除元素 | SREM key member [member …] |
获取所有元素 | SMEMBERS key |
查 元素 是否存在集合(ruturn 0/1 => falet/ture) | SISMEMBER key member |
Zset有序集合(可排序,唯一性) | |
添加元素 | ZADD key score member [score member …] |
获取元素 | ZSCORE key member |
删除元素 | ZREM key member [menber …] |
查 根据 数值进行排列(默认降序) WITHSCORES:查 键、值 | ZREVRANGE key start stop [WITHSCORES] |
元素 递增/递减 (支持正负) | ZINCRBY key increment member |
HyoperLogLog命令 | |
添加元素 | PFADD key element [element …] |
获取指定 HyperLogLog 基数估算值 | PFCOUNT key [key …] |
将多个 HyperLogLog 合并为一个 HyperLogLog | PFMERGE destkey sourcekey [sourcekey …] |
生命周期 | |
设置key生存周期(秒) | EXPIRE key seconds |
查看剩下生存时间 | TTL key |
清除生存时间 | PERSIST key |
其他命令 | |
查所有key | KEYS * |
查所有以user开头的key | KEYS user * |
确认key是否存在(ruturn 0/1 => falet/ture) | EXISTS key |
删除key | DEL key |
重命名key | RENAME oldkey newkey |
获取key值类型 | TYPE key |
获取服务器信息 | INFO |
key移动至指定数据库 | MOVE key db |
切换数据库 | SELECT index |
停止服务器 | SHUTDOWN |
关闭服务连接 | QUIT |
删除当前数据库中的所有key | FLUSHDB |
删除所有数据库中的所有 | FLUSHALL |
HyoperLogLog命令
随机化的算法,以少量内存提供集合唯一的元素数量的近似值
可接受多个元素作为输入,并给出输入元素的基数估算值
基数:集合中不同元素的数量。
例如{‘Sanscan’,‘Bobo’,‘Sanscan’,‘Tomy’,‘Sanscan’}的基数为3估算值:算法给出的基数并非精确,有些许偏差,但 会控制在范围内
命令参考文献: https://redis.io/commands 、 http://doc.redisfans.com/index.html
Redis事务
Redis 事务可以一次执行多个命令, 并且带有以下两个重要的保证:
- 事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客 户端发送来的命令请求所打断
- 事务中的命令要么全部被执行,要么全部都不执行
事务阶段:
- 开始事务
- 命令入队
- 执行事务
事务命令
命令 | 描述 |
---|---|
MULTI | 开始事务 |
DISCARD | 取消事务 |
EXEC | 结束事务 |
Redis订阅
Redis 发布订阅 (pub/sub) 是一种消息通信模式:发送者 (pub) 发送消息,订阅者 (sub) 接收消息
实现方式:
- 开启本地 Redis 服务,开启两个 redis-cli 客户端
- 第一个 redis-cli 客户端输入 SUBSCRIBE runoobChat,意思是订阅
runoobChat
频道- 第二个 redis-cli 客户端输入 PUBLISH runoobChat “Redis PUBLISH test” 往 runoobChat 频道发送消息,这个时候在第一个 redis-cli 客户端就会看到由第二个 redis-cli 客户端发送的测试消息
订阅命令
命令 | 说明 |
---|---|
PSUBSCRIBE pattern [pattern …] | 订阅一个或多个频道 |
PUBLISH channel message | 将信息发送指定频道 |
Redis持久化
Redis值放在内存中,为防止突然断电等特殊情况的发生,需要对数据进行持久化备份。即将内存数据保存到硬盘。
RDB持久化
RDB 是以二进制文件,是在某个时间点将数据写入一个临时文件,持久化结束后,用这个临时文件替换上次持久化的文件,达到数据恢复
RDB 默认开启, redis.conf
文件 中的具体配置参数如下:
#dbfilename:持久化数据存储在本地的文件
dbfilename dump.rdb
#dir:持久化数据存储在本地的路径,如果是在/redis/redis-5.0.5/src下启动的redis-cli,则数据会存储在当前
src目录下
dir ./
##snapshot触发的时机,save
##如下为900秒后,至少有一个变更操作,才会snapshot
##对于此值的设置,需要谨慎,评估系统的变更操作密集程度
##可以通过“save”来关闭snapshot功能
#save时间,以下分别表示更改了1个key时间隔900s进行持久化存储;更改了10个key300s进行存储;更改10000个
key60s进行存储。
save 900 1
save 300 10
save 60 10000
##当snapshot时出现错误无法继续时,是否阻塞客户端“变更操作”,“错误”可能因为磁盘已满/磁盘故障/OS级别异常等
stop-writes-on-bgsave-error yes
##是否启用rdb文件压缩,默认为“yes”,压缩往往意味着“额外的cpu消耗”,同时也意味这较小的文件尺寸以及较短的网
络传输时间
rdbcompression yes
触发机制(snapshots)
写入扳机: 根据写入 key的个数 进行触发 (一个key快照需要900s)
默认情况:1 -> 900s ;300 -> 300s ; 10000 -> 60s数据更新方式: 每次 触发写入扳机 都会替换上次持久化好的文件
AOF持久化
AOF是将 “操作 + 数据” 以格式化指令的方式追加到操作日志文件的尾部,通过append操作进行写入文件,才进行实际数据更变
当需要恢复数据时直接读取此日志文件,还原所有的操作过程,AOF文件内容是字符串,便于阅读。
AOF 默认关闭, redis.conf
文件 中的具体配置参数如下:
开启方法:appendonly yes
##此选项为aof功能的开关,默认为“no”,可以通过“yes”来开启aof功能
##只有在“yes”下,aof重写/文件同步等特性才会生效
appendonly yes
##指定aof文件名称
appendfilename appendonly.aof
##指定aof操作中文件同步策略,有三个合法值:always everysec no,默认为everysec
appendfsync everysec
##在aof-rewrite期间,appendfsync是否暂缓文件同步,"no"表示“不暂缓”,“yes”表示“暂缓”,默认为“no”
no-appendfsync-on-rewrite no
##aof文件rewrite触发的最小文件尺寸(mb,gb),只有大于此aof文件大于此尺寸是才会触发rewrite,默认“64mb”,建
议“512mb”
auto-aof-rewrite-min-size 64mb
##相对于“上一次”rewrite,本次rewrite触发时aof文件应该增长的百分比。
##每一次rewrite之后,redis都会记录下此时“新aof”文件的大小(例如A),那么当aof文件增长到A*(1 + p)之后
##触发下一次rewrite,每一次aof记录的添加,都会检测当前aof文件的尺寸。
auto-aof-rewrite-percentage 100
文件同步策略(appendfsync)
配置原因:AOF 是文件操作,对于变更操作比较密集的 server,那么必将造成磁盘 IO 的负荷加。linux文件操作运用了
延迟写入
的形式,并非每次 写入(write) 都会执行 实际写入 操作,而是写入 缓存(buffer) 中,当 缓存(buffer) 中的数据都达指定 值(阀值) ,才会触发 实际写入 操作。解决方案:可以得知 redis 提供 appendfsync配置 3 个 文件同步策略 选项:
- always:每一条 aof 记录都立即同步到文件,这是最安全的方式,也以为更多的磁盘操作和阻塞延迟,是 IO 开支 较大
- everysec:每秒同步一次,性能和安全都比较中庸的方式,也是 redis 推荐的方式。如果遇到物理服务器故障,有 可能导致最近一秒内 aof 记录丢失(可能为部分丢失)
- no:redis 并不直接调用文件同步,而是交给操作系统来处理,操作系统可以根据 buffer 填充情况 / 通道空闲时间 等择机触发同步;这是一种普通的文件操作方式。性能较好,在物理服务器故障时,数据丢失量会因 OS 配置有关
RDB与AOF区别
RDB
使用单独子进程来进行持久化,主进程不会进行任何 IO 操作
发生故障 将会丢失数据指定存储时长的 key值(根据存储 key的数量 控制时长)
数据内容形式 二进制
AOF
IO 操作会有 1s 的时长进行 实际写入
发生故障 将会丢失数据发生故障前1s的数据
数据形式 字符串
RDB | AOF | |
---|---|---|
加载速度 | 快 | 慢 |
容量大小 | 小 | 大 |
丢失概率 | 高 | 低 |
内容可读 | 否 | 是 |
Redis主从复制
主从复制 是指将 一台Redis服务器(主),拷贝到其他的Redis服务器(从);主从广西只是数据的单向复制,由主节点到从节点
主从复制作用
- 故障恢复:主节点发生故障,由从节点提供服务,直至主节点修复
- 数据冗余:实现数据同步备份,持久化之外的数据备份方式
主从复制原理
- 从机通过配置的 replicaof参数 ,从节点完成主节点 ip 和 port 的保存后,向发送replicaof命令 的客户端直接返回OK
- 连接后从节点先主节点发送 SYNC命令,主节点收到命令立即执行保存快照(持久化文件),并将 缓存的持久化文件 和 缓存写命令 发送给从节点 ,开始同步
- 从节点收到响应,执行 缓存的持久化文件 和 缓存写命令
实现步骤
主机无需配置
- 复制出一个从机 (将 redis文件 夹拷贝)
- 修改从机配置文件
redis.conf
参数replicaof :主机ip + 主机端口 - 修改从机配置文件
redis.conf
参数port :从机端口(自定义) - 清除从机所有的持久化文件
- 启动从机 (注意启动端口)
注意
- 主机发生增删改操作,那么从机会自动将数据同步到从机中
- 从机不能执行写操作,只能读
- 如果主机宕机,从机执行
SLAVEOF NO ONE
命令,提升为为主机继续服务;主机修复后,主机执行SLAVEOF host port
命令,将其恢复主机
Redis哨兵模式
哨兵模式(Sentinel) 是 由一个或多个Sentinel组成的 Sentinel系统 可以监视服务器的上线状态
哨兵模式作用
- 系统监控:独立的进程(哨兵) 对系统实时监控
- 故障切换:主服务器发生故障,会自动将从服务器转为主服务器进行服务(权重)
实现步骤 (Linux实现)
-
从 redis源码配置 中复制
redis-5.0.5/sentinel.conf
(这是我的实例) -
粘贴至 任意服务器节点的
bin
目录下 -
配置
sentinel.conf
中文件 sentinel monitor参数
sentinel monitor <master-name> <ip> <redis-port> <quorum>
例如:sentinel monitor mymaster 192.168.74.131 6380 1
-
指定文件写入日志中,在当前
bin
中 执行以下命令
./redis-sentinel ./sentinel.conf >sent.log &
-
启动 主从服务器
-
启动哨兵监控进程,在
bin
上级目录 执行以下命令
./redis-server redis.conf --sentinel
-
查看 哨兵进程,执行以下命令
ps -aux|grep redis
测试:杀死进程
KILL 9 pid
模拟宕机
注意
- 第三步配置参数的
<master-name>
。如果使用 自定义名称 其他配置参数对应的名称也 需要更改为对应的 自定义名称(否则无效)- 启动哨兵的时候,修改了哨兵的配置文件。如果需要再次启动哨兵,需要删除myid唯一标示
- 哨兵切换 主从服务器 的同时,也会修改
redis.conf
的主从配置文件- 主服务器 故障修复后,需要手动调至 主服务器
SLAVEOF host port
Redis集群
Redis集群是通过添加服务器的数量,提供相同的服务,从而让服务器达到一个稳定、高效的状态
redis-cluste集群方案
Redis-Cluster采用无中心结构,每个节点保存数据和整个集群状态,每个节点都和其他所有节点连接
结构及特点说明
- 所有redis节点都是彼此互联。内部使用二进制协议优化传输速率
- 客户端(client)与redis节点是直连的,无需中间层,client只需连接任意一个redis节点即可应用
- 集群把所有 物理节点映射到 [0-16383] 槽点上,当 Redis集群 存储一个 key-value 时,key 使用 CRC16 算法 算出结果,然后用 结果 对 16384 求余数,最终得到的值 将决定 key放到哪个桶中
- 当 Redis-Cluster 中任意 master 挂掉,且当前 master 没有 slave ,则 Redis-Cluster 为 fail 状态 。 (但 slot映射 不完全进入 fail状态)
- 当 Redis-Cluster 中 master 挂掉一半以上,则 Redis-Cluster 为 fail 状态
slot映射
集群搭建 (Linux实现)
-
新建集群目录,以下是个人用例
[root@bozhuNo1 myapps]# mkdir redis-cluster
-
在 集群 目录下,创建节点目录(复制redis节点),上图已经实例(先配置一个,剩下复制… )
[root@localhost myapps]# cp redis/ redis-cluster/7001 -r [root@localhost myapps]# cd redis-cluster/7001 [root@localhost 7001]# ll drwxr-xr-x. 2 root root 4096 7月 1 10:22 bin -rw-r--r--. 1 root root 3446 7月 1 10:22 dump.rdb -rw-r--r--. 1 root root 41404 7月 1 10:22 redis.conf
-
删除节点根目录下的 持久化文件
appendonly.aof
dump.rdb
-
支持集群,设置 节点根目录下的
redis.conf
配置文件 ,Cluster-enable
参数 设为 yes (默认注释了) -
配置端口,设置 节点根目录下的
redis.conf
配置文件 ,port
参数 设置 端口号 (我们测试的端口范围:[7001-7006]) -
完成一个 redis节点 后 ,剩下节点需要复制粘贴,步骤2开始
-
完成6个 redis节点 后,启动所有节点服务。启动脚本辅助启动6个节点
# vim startall.sh cd 7001 ./bin/redis-server ./redis.conf cd .. cd 7002 ./bin/redis-server ./redis.conf cd .. cd 7003 ./bin/redis-server ./redis.conf cd .. cd 7004 ./bin/redis-server ./redis.conf cd .. cd 7005 ./bin/redis-server ./redis.conf cd .. cd 7006 ./bin/redis-server ./redis.conf cd ..
-
设置 脚本启动权限
chmod u+x startall.sh
-
启动 节点进程服务
./startall.sh
-
创建集群
redis-cli --cluster create ip:port ip:port --cluster-replicas 1
(以下是本人应用实例)[root@bozhuNo1 bin]# cd /home/bozhu/myapps/redis-cluster/7001/bin [root@bozhuNo1 bin]# ./redis-cli --cluster create 192.168.74.131:7001 192.168.74.131:7002 192.168.74.131:7003 192.168.74.131:7004 192.168.74.131:7005 192.168.74.131:7006 --cluster-replicas 1 >>> Performing hash slots allocation on 6 nodes... Master[0] -> Slots 0 - 5460 Master[1] -> Slots 5461 - 10922 Master[2] -> Slots 10923 - 16383 Adding replica 192.168.74.131:7005 to 192.168.74.131:7001 Adding replica 192.168.74.131:7006 to 192.168.74.131:7002 Adding replica 192.168.74.131:7004 to 192.168.74.131:7003 ··· [OK] All 16384 slots covered.
PS:创建前需要关闭防火墙; redis 5.0.5中使用 redis-cli --cluster 替代 redis-trib.rb
-
连接集群(-c:指定是集群连接)
[root@localhost 7001]# ./bin/redis-cli -h 192.168.74.131 -p 7001 -c
查询集群信息:cluster info
;查看集群中节点信息:cluster nodes
Redis分布式锁
分布式锁是多个进程在同一系统中可控制多个进程对资源的访问
Redis为单进程 单线程模式,采用队列模式将并发访问变成串行访问,且多客户端对Redis的连接并不存在竞争 关系。redis也可实现分布式锁
应用满足条件
- 系统是一个分布式的系统
- 资源共享(各个系统访问同一数据库)
- 同步访问(多个进程同时访问同一个资源)
redis分布式锁命令
SETNX(SET if Not eXists)
SETNX key value
如果key已存在,则该命令不做任何操作返回 0 (失败);反之 key不存在,正常赋予key-value值 返回1 (成功)
GETSET
GETSET key value
先获取key对应的旧值,且新值覆盖替换旧值