Redis
一. Redis概述
Redis是一个基于内存存储的,NoSql 非关系型数据库 ,存储结构 : key-value
和nginx一样,Redis也是基于 多路复用IO的原理 实现的。
Redis的特点:
1. 高性能(即,高并发的读写海量的数据).
2. 读写速度极快.
3. 单线程模式.
4. 实现了分布式锁.
5. 不止key-value,Redis提供了5种存储结构.
key-value,key-hash,key-list,key-set,key-sortedSet.
6. ⽀持数据的持久化(RDB、AOF),将内存中的数据保存在磁盘中,重启的时候再次加载进行使用。
7. ⽀持数据的备份,即master-slave模式的数据备份。
Redis的单线程模式:
说白了,同一时间内只有一个线程能够和Redis交互数据,其他的线程都得等着,但是由于Redis的读写速度极快,所以并不存在线程阻塞的问题。
也正是由于这种单线程的特点,Redis才能够用来做分布式锁。
1.Redis数据库为什么读写速度极快:
数据库的工作模式按存储方式可分为:硬盘数据库和内存数据库。
Redis 将数据储存在内存里面,读写数据的时候都不会受到硬盘 I/O 速度的限制,所以速度极快。
(1)硬盘数据库(传统数据库)的工作模式:
(2)内存数据库(比如: Redis)的工作模式:
**以上就是Redis的读写速度极快的原因;**
2. 常见的关系型数据库和非关系型数据库:
除了关系型数据库都是非关系型数据库.
常见的关系型数据库:
mysql,oracle,sqlserver,db2 ...
常见的非关系型数据库:
key-value类型: redis,memecache.
文档存储类型: mongodb, es.
图形化类型: Neo4j
.....
3.Redis的三大用途/本领:
Redis完成的三大件事是很重要的,经常用到!
三大用途:
缓存、分布式锁、Session共享;
4. Redis的五种存储数据的结构:
Redis提供了5种存储数据的结构.
key-value,
key-hash,
key-list,
key-set,
key-sortedSet(zset).
二, Redis的5种数据类型
4.1 String 【单值】
指令 | 描述 |
---|---|
set | 设置一个key/value |
get | 根据key获得对应的value |
mset | 一次设置多个key value |
mget | 一次获得多个key的value |
getset getset age 19 | 获得原始key的值,同时设置新值 |
strlen | 获得对应key存储value的长度 |
append | 为对应key的value追加内容 |
getrange | 截取value的内容,对原始的值没有影响 |
setex setex key ex value | 设置一个key存活的有效期(秒) |
psetex | 设置一个key存活的有效期(豪秒) |
setnx | 只有当这个key不存在时等效set操作 |
msetnx | 可以同时设置多个key,在key不存在时有效 |
decr | 进行数值类型的-1操作 |
decrby | 根据提供的数据进行减法操作 |
incr | 进行数值类型的+1操作 |
incrby | 根据提供的数据进行加法操作 |
incrbyfloat | 根据提供的数据加入浮点数 |
keys *
查看所有key
ttl key
查看key剩余的存活时间
del key
删除key
select 5
切换到第6个库
flushDB
删除当前库的所有数据
4.2 List
指令 | 描述 |
---|---|
lpush | 将某个值加入到一个key列表头部 |
lpushx | 同lpush,但是必须要保证这个key存在 |
rpush | 将某个值加入到一个key列表末尾 |
rpushx | 同rpush,但是必须要保证这个key存在 |
lpop | 返回和移除列表的第一个元素 |
rpop | 返回和移除列表的最后一个元素 |
lrange | 获取某一个下标区间内的元素 |
llen | 获取列表元素个数 |
lset lset key index value | 设置某一个位置的元素(替换已有的某个值) |
lindex lindex key index | 获取某一个位置的元素 |
lrem lrem key 2 xxx | 从列表头起,删除对应个数的指定元素 |
ltrim | 保留列表中特定区间内的元素,将其他的元素删除 |
linsert key after/before old new | 在某一个元素之前,之后插入新元素 |
4.3 Set
指令 | 描述 |
---|---|
sadd | 为集合添加元素 |
smembers | 显示集合中所有元素 无序 |
scard | 返回集合中元素的个数 |
spop | 随机返回并移除一个元素 |
smove smove setFrom setTo xxx | 从一个集合中向另一个集合移动元素 |
srem | 从集合中删除一个元素 |
sismember sismember set77 值 | 判断一个集合中是否含有这个元素 |
srandmember | 随机返回元素,对原始数据没有影响 |
sdiff sdiff seta setb | 减去两个集合中共有的元素 |
sinter | 求交集 |
sunion | 求并集 |
4.4 ZSet
指令 | 描述 |
---|---|
zadd zadd key 10 a 5 b 30 c | 添加一个有序集合元素,根据元素的score排序 |
zcard | 返回集合的元素个数 |
zrange | 返回一个范围内的元素 |
zrangebyscore | 按照分数查找一个范围内的元素 |
zrank zrank key xx | 返回对应元素的排名 |
zrevrank | 返回对应元素倒序排名 |
zscore zscore key xxx | 显示某一个元素的分数 |
zrem | 移除某一个元素 |
zincrby zincrby key 10 lining | 给某个特定元素加分 |
4.5 Hash
指令 | 描述 |
---|---|
hset | 设置一个key/value对 |
hget | 获得一个key对应的value |
hgetall | 获得所有的key/value对 |
hdel | 删除某一个key/value对 |
hexists | 判断一个key是否存在 |
hkeys | 获得所有的key |
hvals | 获得所有的value |
hmset | 设置多个key/value |
hmget | 获得多个key的value |
hsetnx | 设置一个不存在的key的值 |
hincrby hincrby key k 2 | 为value进行加法运算 |
hincrbyfloat | 为value加入浮点值 |
三. redis的基本命令.(重要)
redis的命令中文文档: http://doc.redisfans.com/
一,key:
1. del. -> 删除指定的key
del key...
2. expire. -> 指定key的生存时间.
expire key seconds
4. keys. -> 查询当前redis中的全部key.
keys pattern.
(* ? [具体字符])
5. pexpire. -> 设置key的生存时间.单位为毫秒.
pexpire key milliseconds
6. ttl -> 获取key过期时间
ttl key
(-2: 当前key不存在. -1: 当前key没有生存时间. >=0 : 具体的剩余生存时间.)
二,string:
1. incr -> 给key的value自增1.
incr key
(如果value是非数值,会报错.)
2. decr -> 给key的value自减1.
decr key
3. incrby -> 给key的value指定自增具体的数字.
incrby key increment
4. set -> 设值.
set key value
5. get -> 取值.
get key
6. setnx -> 设值, 如果key存在,则设值失败, 如果key不存在,和set一模一样.
setnx key value
返回值:
设置成功,返回 1 。
设置失败,返回 0 。
7. getset -> 先取老值,再设新值.
getset key value
三、hash 哈希
hset key field value 设置键值
hmset key field1 value1 field2 vlaue2 ... 为多个key设置值
hkeys key 获取key的所有属性
hget key field 获取值
hmget keys key1 field1 key2 field2 .. 获取多个key的值
四、List 链表
lpush key value 在链表的左侧追加元素
rpush key value 在链表的右侧追加元素
llen 获取列表的长度
五、set 集合 不能重复 无序
sadd key member1 member2 ... 添加元素
smemebers key 获取元素
srem key members 删除元素
六、zset 有序集合
zadd key score1 member1 score2 member2 ... ... 添加元素
zrange key start end 获取元素
zcore key member 查看成员的权重
zrem key member1 member2 ... 删除成员
四. Redis的持久化机制
Redis的持久化机制、RDB和AOF的概念以及区别,这是重点。
1)为什么要持久化:
**redis是基于内存存储的nosql非关系型数据库,为了使Redis在重启的时候,数据不丢失,所以要将Redis中的数据持久化到磁盘上。**
2)RDB机制
1. RDB的原理
1> 在某些时刻,Redis通过fork函数产生一个子进程和一个父进程的副本, 2> 父进程继续处理客户端请求,子进程负责将父进程的副本写入一个临时的rdb快照文件中, 3> 子进程写完后,用这个临时文件替换掉原来的旧的临时文件,然后子进程退出。
补充:什么是快照文件?
快照是数据存储的某一时刻的状态记录; **简单来说,快照文件,就是该文件在某个时间点的一个副本;** 一个文件可以有多个文件快照; 一个文件快照只能来源于一个文件 ;
3) AOF机制
1 原理
1> Redis将每一个写操作(执行成功后),就将数据写入一个aof文件,
2> Redis重启时只要从头到尾执行一次aof文件,即可恢复数据;
**也可以将aof文件复制到别的服务器,做数据移植**
注意:在重启时,要恢复数据,如果rdb文件和aof文件同时存在,以AOF为准
2 细节
1> AOF文件会不断增长(可能比快照文件大几倍),在极端情况下,可能会对硬盘空间造成压力
2> Redis重启时,需要重新执行一个可能非常大的AOF,时间会很长
3> AOF同步时间间隔小,数据更安全,比rdb更擅长做更实时的持久化
4) RDB和AOF的区别:
1. Redis默认的持久化机制是RDB,而AOF机制默认是关闭着的;
2. RDB文件是二进制文件,而AOF文件是普通的文本文件;
3. RDB的持久化的速度快,AOF持久化的速度慢;
4. RDB持久化的文件小,AOF持久化的文件大;
5. 在服务器重启时,要恢复数据,如果rdb文件和aof文件同时存在,以AOF文件为准。原因:AOF持久化的时间间隔小,因而数据更安全;
五,Redis事务机制:
1)Redis的事务机制的特点:
1. 将一些命令放到一个队列中.(也就是Redis命令的执行是有顺序的)
2. 当提交事务时,队列中的命令会有序的执行,不会受外界干扰. (要么都执行,要么都不执行)
3. redis命令执行的成功或失败,redis是不管的(一般情况下,只要你输入的语法没有问题,是不会失败的)
六, Redis模式一:主从模式(一主多从)
1)介绍:
**redis的主从模式,指的是针对多台redis实例的时候,即,只存在一台主服务器master,提供读写的功能,同时存在多台依附于这台主服务器的从服务器slaver,只提供读服务,且数据和主服务器保持一致。** **主服务器只能有一台,从服务器可以有多台,而且可以存在级联模式(从服务器下面也挂载从服务器)。**
2) 原理
**在处理大量复杂的数据时,Redis的`主从复制`模式,将有效保证redis的高性能。**
3)Redis主从模式的 特点:
1> **一个Redis主服务器,并为其关联多个从服务器,主服务器会将自己的数据不断的同步给从服务器。** 2> **主服务器负责写操作,从服务器负责读操作。** 3> **主服务器的所有数据会在第一次接收到从服务器的连接时,全部发送到从服务器。之后主服务器每次执行完一个写操作后,都会将新的数据发送给从服务器。**
4)Redis主从模式的优缺点:
第一个优点:读写分离
即,主节点只负责写操作,从节点只负责读操作;
第二个优点:数据同步
即,主节点在写完数据之后,会异步的同步数据给从节点们。所以这种的主从结构,所有的节点存储的数据都是一模一样的!
第三个优点:(多搭几个从节点),就可以做到了对读操作的高并发能力;
缺陷:
和单个Redis服务器一样,最多还是只能存20G的数据;
存在单点故障,如果主节点挂掉了,整个Redis服务就挂掉了;
主节点挂掉后,需要人工的将一个从节点升级为主节点;
七, Redis的哨兵机制.
1)介绍:
因为Redis没有master自动选举功能,所以在Redis的主从结构中,主节点挂掉后,需要人工的将一个从节点升级为主节点;
而人工明显很费劲,所以,使用哨兵机制;
哨兵机制:
由哨兵来监控整个Redis系统的运行;
哨兵它的主要功能是:监控master节点和slave节点是否正常运行;
当master节点出现故障时,自动的将一个slave从节点 升级为 master主节点。(PS:至于选择哪个从节点,完全是随机的,因为都一样。)
2)哨兵机制的主要功能如下:
1) 集群监控,负责监控redis master 和slave进程是否正常工作。
2) 消息通知,如果某个redis实例发生故障了,那么哨兵将会发送报警,通知给管理员。
3) 故障迁移,(就是自动上位),如果一个master主节点挂掉了,哨兵会将失效Master的其中一个Slave从节点升级为新的Master。并让失效Master的其他Slave改为连接新的Master; 当客户端试图连接失效的Master时,集群也会向客户端返回新Master的地址。
使用哨兵后的架构图:
3)哨兵集群:
为了保证哨兵的可用性,可以使用多个哨兵进行“全方位监控”。
此时哨兵不仅会监控master和slave,同时还会互相监控;
这种方式称为哨兵集群。
使用哨兵集群后的架构图:

八,Redis模式二,集群模式 (多主多从)
1)介绍:
**redis Cluster(集群) :集群模式,指的是针对多个redis实例,`去中心化`,即,Redis集群中的每个节点都是平等的关系,都是对等的,** **每个节点都保存各自的数据和整个集群的状态,并且每个节点都和其他所有节点保持连接,这样就保证了我们只需要连接redis集群中的任意一个节点,就可以获取到其他节点的数据。** **一个Redis集群,至少有6台redis服务器;**
2) redis集群的架构.
redis集群模式是Redis3.0版本之后,用来解决高可用、高并发等问题而出现的。
1> 注意:redis集群中,节点的数量≠服务器的数量,
从节点不算节点,它只是主节点的备份机而已;
比如,一个redis集群中,有3个节点,每个节点有一个备份机(从节点),所以这个集群有6台服务器、有3个节点。
一般一个主节点有一个从节点(备份机)就可以了,即,一主配一从。如果数据特别重要,可以改成一个主节点配多个从节点(备份机),即,一主配多从;
一个Redis的集群,至少有6台redis服务器;
2> Redis集群的5大特点:
1. 它是,无中心的集群架构模式;
2. 主从节点之间不再做读写分离,从节点只做为数据备份这一件事(不干其他事),仅仅是作为备份机的身份存在;
3. ping-pang机制,即,每个master主节点之间是有联系的,即,ping-pang机制。
4. 投票机制,当一个主节点挂掉后,只有超过半数以上的其他主节点都认为该主节点挂掉了,才认为该节点真的挂掉了,然后选一个从节点,上位成为主节点;
5. Redis的集群,有16384个哈希槽,不同的节点维护者不同范围的哈希槽;当有客户端请求进行写数据时,会对将要写入Redis的这个数据先进行hash计算,再将计算后的结果对16384取余,根据余数对号入座,将数据写入到相应的主节点中。
3> 哈希槽的分配:
哈希槽可以理解为是一个存储数据的位置。
整个redis集群有16384个哈希槽,决定一个key应该分配到哪个槽的算法是:计算该key的CRC16结果,再模上16834。
集群中的每个(主)节点负责一部分哈希槽,比如集群中有3个(主)节点,则:
● 节点A存储的哈希槽范围是:0 – 5500
● 节点B存储的哈希槽范围是:5501 – 11000
● 节点C存储的哈希槽范围是:11001 – 16384
这样的哈希槽分布方式,更加方便节点的增删。比如,需要新增一个节点D,只需要把A、B、C中的部分哈希槽数据移到D节点。同样,如果希望在集群中删除A节点,只需要把A节点的哈希槽的数据移到B和C节点即可。
4> ping pang机制指的是:
当A主节点给B主节点发去一个消息时(ping),B_master必须要返回来一个消息(pang);
如果没有的话,则A_master会认为B_master死掉了,然后通知其他的master主节点也去试探一下B-master是否挂掉了,当超过半数以上的master都认为B_master挂掉了,则宣布B_matser正式挂掉了,然后B_master的一个从服务器上位成为新的B_master。
九,Redis实现分布式锁:
使用的命令介绍:
(1)SETNX
SETNX key val:当且仅当key不存在时,set一个key为val的字符串,返回1;
若key存在,则什么都不做,返回0。
(2)expire
expire key timeout:为key设置一个超时时间,单位为second,超过这个时间锁会自动释放,避免死锁。
(3)delete
delete key:删除key,即,释放锁。
在使用Redis实现分布式锁的时候,主要就会使用到这三个命令。
条件:
设置一个key,所有线程的key都是这同一个key,比如:“粽子”;
流程:
- 线程1先执行setnx方法,申请获取锁资源,
- setnx返回的结果为1,所以线程1获取到了锁资源,开始处理请求,此时并通过expire方法设置一个过期时间;
- 未超时的时候:
- 如果,线程1还未释放锁资源:
其他的线程尝试获取锁资源,先执行setnx方法,由于所有线程的key都是这同一个key,所以setnx返回的结果为0,判定为获取锁资源失败。
- 如果,线程1释放了锁资源:
其他的线程们开始抢夺锁资源,抢到了锁资源的那个线程开始执行处理(并设置过期时间),其他的线程则继续等待;
- 超时的时候:
- 强制迫使线程1释放锁资源,然后其他的线程们开始抢夺锁资源...