1.Redis的基本介绍:
Redis是一个开放源代码(BSD许可)的内存数据结构存储,可以用作数据库、缓存和消息代理;支持字符串、哈希、列表、集合、带范围查询的排序集合等数据结构。Redis具有内置的复制、Lua脚本、LRU收回、事务和不同级别的磁盘上持久性,并通过Redis Sentinel和Redis群集的自动分区提供高可用性。
源码地址:https://github.com/antirez/redis
官方网站:https://redis.io
2.Redis的特点
1、内存数据库,速度快;支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载使用。
2.Redis不仅仅支持简单的key-value类型的数据,同时还提供listt,set,zset,hash等数据结构(Redis5.0新增了Stream)
3.Redis支持数据的备份,即主从模式的数据备份,数据可扩展性高。
3.Redis的优势
1):性能极高 Redis读的速度是110000次/s,写的速度是81000次/秒
2):丰富的数据类型:String,List,Hash,Set及Sorted Set数据类型(Stream)
3):原子性:Redis的所有操作都是原子性的。
4):Redis可用于缓存,消息队列,排行榜,点赞等。
4、Redis的安装、、
安装步骤:见下一篇
目前官网的稳定版本是5.0.5版本,Redis官网不提供windows版本。
Window64位下载地址:https://github.com/MicrosoftArchive/redis/releases
5.Redis的多数据库特点
Redis默认支持16个数据库,以一个从0开始的递增数字命名,可以通过redis.conf文件中的参数databases来修改默认是数据库的个数,客户端连接Redis服务后会自动选择0号数据库,可以通过Select命令更换数据库,例如选择15号数据库

# src/redis-cli
select 15

不支持为每个数据库设置访问密码
多个数据库 之间不是完全隔离的,FLUSHALL命令会清空所有数据库的数据。
多个数据库不适用存储不同应用的数据
Redis集群不支持多数据库
6.Redis的数据类型
String、hash .list set
命令举例:
sadd:添加元素
smembers:获取集合中的所有元素
sismember:判断集合是否在元素中
srem:删除元素
scard:获取元素的个数,相当于count
spop:随机返回删除的元素
sdiff:差集,返回在第一个set里面而不再后面任何一个set里面的项
sdiffstore:差集并保留结果
sinter:交集 返回多个set里面都有的项
sinterstore:交集并保留结果
sunion:并集
sunionstore:并集并保留结果
smove:移动元素到另一个集合
Zset类型
7.Redis主从模式

1)Redsi主从复制模式

Master可以有多个slave,Slave也可以连接其它的Slave
Slave同步Master数据时,Mater不会阻塞,可以继续处理client的读写请求(乐观复制策略)、
Master主库可以进行读写操作,Slave从库一般只是进行读操作
2)主从复制的基本原理
Slave启动时,向master 发送sync命令,2.8版本发送psync,以实现增量复制

Master接到sync请求后,会在后台保存快照,也就是实现RDB持久化,并将保存快照期间接受到命令缓存起来

快照完成后,Master会将快照文件和所有缓存的命令发送给从库
slave接受后,会载入快照文件并执行缓存命令,从而完成复制的初始化
在数据库使用阶段,Master(主库)会自动把每次收到的写命令同步到从服务器

3). Redis乐观复制策略
Redis采用乐观复制的策略,允许一定时间内主从数据库的内容不同,当然最终的数据会相同。此策略保证了Redis性能,在进行复制时,Master(主库)并不阻塞,继续处理client的请求。
但是Redis同样提供了配置用来限制只有当数据库至少同步给指定数量的Slave(从库)时,Master(主库)才可写,否则返回错误。配置是:min-slaves-to-write、min-slaves-max-lag。
4)主从配置 配置redis.conf

Master配置
bind 127.0.0.1 # 注释掉
protected-mode no # 关闭保护模式(将yes改为no)
daemonize yes     # 守护进程模式开启(将no改为yes)
dir /opt/redis/data/ # 默认是./,表示在redis目录下生成dump.rdb,用于持久化数据; 
logfile "/opt/redis/logs/redis.log"
Slave配置
bind 127.0.0.1       # 注释掉
protected-mode no  # 关闭保护模式
daemonize yes       # 守护进程模式开启
dir /opt/redis/data/默认是./,表示在redis目录下生成dump.rdb,用于持久化数据; 
logfile “/opt/redis/logs/redis.log”
replicaof master-ip master-port

8.Redis哨兵模式
主从集群有个问题,就是Master(主库)挂了之后,无法重新选举新的节点作为主节点进行 写操作,导致服务不可用
Redis提供了哨兵工具来实现监控Redis系统的运行情况,能够实现如下功能:
监控主从数据库运行是否正常。
当主数据库出现故障时,自动将从数据库转换为主数据库。
使用Redis-sentinel,redis实例必须在非集群模式下运行。

配置哨兵模式 配置sentinel.conf文件

daemonize yes     # 改为yes
logfile "/opt/redis-shaobing/logs/sentinel.log" 
sentinel monitor mymaster 192.168.17.129 6379 1
sentinel down-after-milliseconds mymaster 5000  # 改为5s,默认30s

启动哨兵:/opt/redis-shaobing/src/redis-sentinel /opt/redis-shaobing/sentinel.conf
进入哨兵:/opt/redis-shaobing/src/redis-cli -h 192.168.17.129 -p 26379
查看哨兵信息:/opt/redis-shaobing/src/redis-cli -h 192.168.17.129 -p 26379 info Sentinel
9.Redis集群
Redis集群是一个提供在多个Redis节点间共享数据的程序集
Redis集群并不支持处理多个keys的命令(比如mset、mget等)因为这需要在不同的节点间移动数据,从而达不到像Redis哪样的性能,在高负载情况下可能会导致不可预料的错误
Redis集群通过分区来提供一定程度的可用性,在实际环境中当某个节点宕机或者不可达的情况下继续处理命令

Redis集群的优势
自动分割数据到不同的节点上
整个集群的部分节点失败或者不可达的情况下能够继续处理命令
11. Redis 集群的数据分片
Redis集群引入了哈希槽的概念。
Redis 集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽。集群的每个节点负责一部分hash槽。
举个例子:比如当前集群有3个节点,那么:节点 A 包含 0 到 5500号哈希槽。节点 B 包含5501 到 11000 号哈希槽。节点 C 包含11001 到 16383号哈希槽。
这种结构很容易添加或者删除节点: 比如我们想新添加个节点D, 我们需要将节点 A、B、 C中的部分槽移动到D上。如果我想移除节点A,需要将A中的槽移到B和C节点上。然后将没有任何槽的A节点从集群中移除即可。由于从一个节点将哈希槽移动到另一个节点并不会停止服务,所以无论添加删除或者改变某个节点的哈希槽的数量都不会造成集群不可用的状态.

12.Redis的事务
Redis对事务的支持比较简单,它是一组命令的集合,命令被依次顺序的执行,也可以放弃事务的执行,此时所有事务里面的命令都不会执行。

Redis 只能保证一个client发起的事务中的命令可以连续的执行,而中间不会插入其他client的命令,因为Redis是单线程架构,所以在执行完事务内所有指令前是不可能再去同时执行其他客户端的请求的

Redis事务没有隔离级别的概念,因为事务提交前任何指令都不会被实际执行
Redis的事务不保证原子性,也就是不保证所有指令同时成功或同时失败,只有决定是否开始执行全部指令的能力,没有执行到一半进行回滚的能力
事务操作的基本命令
multi:设置事务开始
exec:执行事务
discard:放弃事务
watch:监控键值,如果键值被修改或者删除,后面的一个事务就不会执行
unwatch:取消watch
13. 事务扩展-乐观锁
观锁大多是基于数据版本(version)的记录机制实现的。何谓数据版本?即为数据增加一个版本标识,更新数据时,对此版本号加 1,当线程A要更新数据值时,在读取数据的同时也会读取version值,在提交更新时,若刚才读取到的version值为当前数据库中的version值大于时才更新,否则更新失败。

6.3.2.	乐观锁举例
小明的账户有余额1000刀;
(1)操作员A将小明的信息读出(此时 version=1),并准备从其帐户余额中扣除100刀(1000-100); 900
(2)在操作员A操作的过程中,操作员B也读入小明的信息(此时 version=1),并准备从其帐户余额中扣除500刀(1000-500); 500
(3)A完成了修改工作后,将数据版本号加 1(此时 version=2),帐户扣除后余额为900刀,提交至数据库更新,此时由于提交数据版本大于数据库记录当前版本(2>1),数据被更新,数据库记录 version 更新为 2;
 (4)在A完成更新操作之后,B也完成了操作,她也将版本号加 1(version=2)并试图向数据库提交数据(此时小明的余额为500刀),但比对数据库记录版本时发现,B提交的数据版本号为 2,数据库记录当前版本也为 2,不满足“提交版本必须大于记录当前版本才能执行更新”的乐观锁策略,因此,B的提交被驳回;

14. Redis事务的基本过程
1.发送一个事务的命令multi给redis;
2.依次把要执行的命令发送给redis,redis接到这些命令,并不会立即执行,而是放到等待执行的事务队列里面;
3.发送执行事务的命令exec给redis;
4.redis会保证一个事务内的命令依次执行,而不会被其它命令插入
15. Redis持久化
Redis的持久化方案目前有两种方式:RDB和AOF模式

RDB持久化
实现机制 rdb方式是通过在是一定时间内将内存中的数据集快照(Snapshot)写入磁盘;在数据恢复时,再将快照中的信息读取到内存中。
RDB持久化是Redis定期将内存中的"数据集快照"写入磁盘,实际操作过程是创建(fork)一个子进程,先将数据集写入临时文件,写入成功后,再替换之前的文件,用二进制压缩存储。整个过程主进程不进行任何IO操作,保证Redis性能的高效性。
RDB持久化的触发方式:自动触发和手动触发

手动触发

save命令:执行此命令会阻塞Redis服务器,执行命令期间,Redis不能处理其它命令,直到RDB过程完成为止。
bgsave命令:执行该命令时,Redis会在后台异步进行快照操作,做快照的同时还可以响应客户端请求;此时Redis进程执行fork操作创建子进程,RDB持久化过程由子进程负责,完成后自动结束。阻塞只发生在fork阶段,一般时间很短。

AOF持久化
AOF持久化以日志的形式记录服务器所处理的每一个写、删除操作,查询操作不会记录,以文本的方式记录,可以打开文件看到详细的操作记录

默认情况下,redis会在后台异步的把数据库镜像备份到磁盘,但是该备份是非常耗时的,而且备份也不能很频繁,如果发生断电等状况,那么将造成比较大范围的数据丢失。(rdb)
# 所以redis提供了另外一种更加高效的数据库备份及灾难恢复方式。
# 开启append only模式之后,redis会把所接收到的每一次写操作请求都追加到appendonly.aof文件中,当redis重新启动时,会从该文件恢复出之前的状态。
# 但是这样会造成appendonly.aof文件过大,所以redis还支持了BGREWRITEAOF指令,对appendonly.aof 进行重新整理。
# 你可以同时开启asynchronous dumps 和 AOF
appendonly yes
# AOF文件名称 (默认: "appendonly.aof")
appendfilename appendonly.aof 

 Redis支持三种同步AOF文件的策略: 
# no: 不进行同步. Faster.
# always: always表示每次有写操作都进行同步. Slow, Safest.
# everysec: 表示对写操作进行累积,每秒同步一次. Compromise. 

 AOF 自动重写
# 当AOF文件增长到一定大小的时候Redis能够调用 BGREWRITEAOF 对日志文件进行重写 
# 它是这样工作的:Redis会记住上次进行些日志后文件的大小(如果从开机以来还没进行过重写,那日志大小在开机的时候确定)

Redis发布与订阅:
Redis的发布订阅模式可以实现进程间的消息传递
8.2. 发布订阅模式的操作指令
publish:发布消息,格式是:publish channel消息
subscribe:订阅消息,格式是:subscribe channel, 可以是多个channel
psubscribe:订阅消息,格式是:psubscribe channel, 支持glob风格的通配符
unsubscribe:取消订阅,格式是:unsubscribe channel,不指定频道表示取消所有subscribe命令的订阅
punsubscribe:取消订阅,格式是:punsubscribe channel,不指定频道表示取消所有的punsubscribe命令的订阅,注意这里匹配模式的时候,是不会将通配符展开的,是严格进行字符串匹配的,比如:punsubscribe * 是无法退订 c1.的,
必须严格使用punsubscribe c1.
才可以。

Redis的Java客户端Jedis

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.0.1</version>
</dependency>

Spring 整合jedis
Spring-data-redis

Redsi的安装
Redis集群的安装见下篇