Redis

一、前言

redis官网

redis 中文 官网

redis 命令帮助文档

redis 图形化工具AnotherRedisDesktopManager

1、NoSQL的引言

  NoSQL(Not Only SQL ),意即不仅仅是SQL, 泛指非关系型的数据库。Nosql这个技术门类,早期就有人提出,发展至2009年趋势越发高涨。

2、为什么是NoSQL

  随着互联网网站的兴起,传统的关系数据库在应付动态网站,特别是超大规模和高并发的纯动态网站已经显得力不从心,暴露了很多难以克服的问题。如商城网站中对商品数据频繁查询对热搜商品的排行统计订单超时问题、以及微信朋友圈(音频,视频)存储等相关使用传统的关系型数据库实现就显得非常复杂,虽然能实现相应功能但是在性能上却不是那么乐观。nosql这个技术门类的出现,更好的解决了这些问题,它告诉了世界不仅仅是sql。

3、NoSQL的四大分类

3.1 键值(Key-Value)型存储数据库

  • 说明

这一类数据库主要会使用到一个哈希表,这个表中有一个特定的键和一个指针指向特定的数据。

  • 特点

Key/value模型对于IT系统来说的优势在于简单、易部署

但是如果DBA只对部分值进行查询或更新的时候,Key/value就显得效率低下了。

  • 相关产品

Tokyo Cabinet/Tyrant、Redis、SSDB、Voldemort 、Oracle BDB

3.2 列型存储数据库

  • 说明

这部分数据库通常是用来应对分布式存储的海量数据。

  • 特点

键仍然存在,但是它们的特点是指向了多个列。这些列是由列家族来安排的。

  • 相关产品

Cassandra、HBase、Riak

3.3 文档型数据库

  • 说明

文档型数据库的灵感是来自于Lotus Notes办公软件的,而且它同第一种键值存储相类似该类型的数据模型是版本化的文档,半结构化的文档以特定的格式存储,比如JSON。文档型数据库可 以看作是键值数据库的升级版,允许之间嵌套键值。而且文档型数据库比键值数据库的查询效率更高

  • 特点

以文档形式存储

  • 相关产品

MongoDB、CouchDB、 MongoDb(4.x). 国内也有文档型数据库SequoiaDB,已经开源。

3.4 图形(Graph)数据库

  • 说明

图形结构的数据库同其他行列以及刚性结构的SQL数据库不同,它是使用灵活的图形模型,并且能够扩展到多个服务器上。

NoSQL数据库没有标准的查询语言(SQL),因此进行数据库查询需要制定数据模型。许多NoSQL数据库都有REST式的数据接口或者查询API。

  • 特点

...

  • 相关产品

Neo4J、InfoGrid、 Infinite Graph、


4. NoSQL应用场景

  • 数据模型比较简单
  • 需要灵活性更强的IT系统
  • 对数据库性能要求较高
  • 不需要高度的数据一致性

二、redis

1、redis简介

redis 是一个开源免费的高性能的 key value 数据库。
支持数据持久化,即可以将内存的数据存储在磁盘中,重启服务后可以再次加载磁盘中的数据并使用。
支持多种类型,比如:String(字符串)、List(列表)、Set(集合)、zset(有序集合)、Hash(散列) 等。
支持数据备份,主从模式的数据备份(master slave)。
redis 所有操作都是原子性的,即要么成功执行,要么不执行。

2、Redis特点

  • Redis是一个高性能key/value内存型数据库
  • Redis支持丰富的数据类型
  • Redis支持持久化
  • Redis单线程,单进程

3、安装

推荐使用docker安装

# 官网
https://redis.io/

$ mkdir -p /opt/redis && cd /opt/redis
$ wget http://download.redis.io/releases/redis-4.0.10.tar.gz 
$ tar -zxvf redis-4.0.10.tar.gz
# 安装gcc用于编译源码
$ yum install -y gcc

# 编译方式一(编译结果文件在src目录里面)
$ cd /opt/redis/redis-4.0.10
$ make

# 推荐:编译方式二(指定编译输出到bin目录下)
$ pwd 
/opt/redis/redis-4.0.10/src
$ make install PREFIX=/opt/redis/redis-4.0.10

# 移动配置文件路径
$ mkdir /opt/redis/redis-4.0.10/bin/config
$ cp /opt/redis/redis-4.0.10/redis.conf /opt/redis/redis-4.0.10/bin/config/

# 配置redis为后台启动
# 将daemonize no 改成daemonize yes
$ vim /opt/redis/redis-4.0.10/bin/config/redis.conf

# 启动
$ /opt/redis/redis-4.0.10/bin/redis-server /opt/redis/redis-4.0.10/bin/config/redis.conf

# 客户端连接
$ /opt/redis/redis-4.0.10/bin/redis-cli -p 6379

# 查看命令帮助
$ /opt/redis/redis-4.0.10/bin/redis-cli -h

3.1 配置redis密码验证

# 建立连接
$ redis-cli -p 6379

# 查看密码
127.0.0.1:6379> config get requirepass

# 设置密码
127.0.0.1:6379> config set requirepass 密码

# 登录时直接验证
$ redis-cli -p 6379 -a 密码
    
# 先登陆后验证
$ redis-cli -p 6379
$ redis 127.0.0.1:6379> auth 密码

3.2 修改配置

# 绑定网卡
bind 127.0.0.1
# 是否开启保护模式(正式环境一般都是开启)
protected-mode no

4、Redis数据库相关指令

4.1 数据库操作指令

# 1.Redis中库说明
使用redis的默认配置器动redis服务后,默认会存在16个库,编号从0-15
可以使用select 库的编号 来选择一个redis的库

# 2.Redis中操作库的指令
清空当前的库  FLUSHDB
清空全部的库  FLUSHALL

4.2 操作指令大全

Redis 命令参考

4.3 常用数据结构及相关命令

https://www.cnblogs.com/l-y-h/p/12656614.html#_label6

4.4 Redis数据结构底层实现原理

https://blog.csdn.net/a745233700/article/details/113449889

5、java操作Redis

5.1 引入依赖

<!--引入jedis连接依赖-->
<dependency>
  <groupId>redis.clients</groupId>
  <artifactId>jedis</artifactId>
  <version>2.9.0</version>
</dependency>

5.2 使用

 public static void main(String[] args) {
   //1.创建jedis对象
   //redis服务必须关闭防火墙  2.redis服务必须开启远程连接
   Jedis jedis = new Jedis("192.168.40.4", 6379);
   jedis.select(0);//选择操作的库默认0号库
   //2.执行相关操作
   //....
   //3.释放资源
   jedis.close();
 }

6、SpringBoot使用Redis

  Spring Boot Data(数据) Redis 中提供了RedisTemplate和StringRedisTemplate,其中StringRedisTemplate是RedisTemplate的子类,两个方法基本一致,不同之处主要体现在操作的数据类型不同,RedisTemplate中的两个泛型都是Object,意味着存储的key和value都可以是一个对象,而StringRedisTemplate的两个泛型都是String,意味着StringRedisTemplate的key和value都只能是字符串。

注意: 使用RedisTemplate默认是将对象序列化到Redis中,所以放入的对象必须实现对象序列化接口

6.1 引入依赖

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

6.2 修改配置

spring.redis.host=localhost
spring.redis.port=6379
spring.redis.database=0

6.3 使用

	@Autowired
    private StringRedisTemplate stringRedisTemplate;  // 对字符串支持比较友好
    @Autowired
    private RedisTemplate redisTemplate;  // 存储对象

三、底层原理

1、持久化机制

Redis的持久化机制-张维鹏:https://blog.csdn.net/a745233700/article/details/112726827

目的:内存 --->>> 磁盘

官方提供两种不同持久化方案将数据持久化存储到硬盘:

  • RDB(Redis DataBase 快照模式)
  • AOF (Append Only File 日志记录)

1.1 RDB

1. 特点

这种方式可以将某一时刻的所有数据都写入硬盘中,当然这也是redis的默认开启持久化方式,保存的文件是以.rdb形式结尾的文件因此这种方式也称之为RDB方式。

2. 快照生成方式

  • 客户端方式: BGSAVE 和 SAVE指令
  • 服务器配置自动触发
# 客户端方式之BGSAVE

  客户端可以使用BGSAVE命令来创建一个快照,当服务端接收到客户端的BGSAVE命令时,redis服务端会调用fork来创建一个子进程,然后子进程负责将快照写入磁盘中,而父进程则继续处理命令请求。

名词解释: fork当一个进程创建子进程的时候,底层的操作系统会创建该进程的一个副本,在类unix系统中创建子进程的操作会进行优化:在刚开始的时候,父子进程共享相同内存,直到父进程或子进程对内存进行了写之后,对被写入的内存的共享才会结束服务。

# 2.客户端方式之SAVE

  客户端还可以使用SAVE命令来创建一个快照,接收到SAVE命令的redis服务器在快照创建完毕之前将不再响应任何其他的命令

  • 注意: SAVE命令并不常用,使用SAVE命令在快照创建完毕之前,redis处于阻塞状态,无法对外服务
# 3.服务器配置方式之满足配置自动触发

  如果用户在redis.conf中设置了save配置选项,redis会在save选项条件满足之后自动触发一次BGSAVE命令,如果设置多个save配置选项,当任意一个save配置选项条件满足,redis也会触发一次BGSAVE命令

# 4.服务器接收客户端shutdown指令

  当redis通过shutdown指令接收到关闭服务器的请求时,服务器在关闭前会自动执行一次save命令,阻塞所有的客户端,不再执行客户端发送的任何命令,并且在save命令执行完毕之后关闭服务器

3. 配置生成快照名称和位置

# 1.修改生成快照名称
dbfilename dump.rdb

# 2.修改生成位置
dir ./

1.2 AOF

1.特点

  这种方式可以将所有客户端执行的写命令记录到日志文件中,AOF持久化会将被执行的写命令写到AOF的文件末尾,以此来记录数据发生的变化,因此只要redis从头到尾执行一次AOF文件所包含的所有写命令,就可以恢复AOF文件的记录的数据集

2.开启AOF持久化

在redis的默认配置中AOF持久化机制是没有开启的,需要在配置中开启

# 1.开启AOF持久化

appendonly yes
appendfilename "appendonly.aof"

3.日志追加频率

  • always 【谨慎使用】

说明:每个redis写命令都立即同步写入硬盘,严重降低redis速度

解释:如果用户使用了always选项,那么每个redis写命令都会立即被写入硬盘,从而将发生系统崩溃时出现的数据丢失减到最少;遗憾的是,因为这种同步策略需要对硬盘进行大量的写入操作,所以redis处理命令的速度会受到硬盘性能的限制;

注意:转盘式硬盘在这种频率下200左右个命令/s ; 固态硬盘(SSD) 几百万个命令/s;

警告:使用SSD用户请谨慎使用always选项,这种模式不断写入少量数据的做法有可能会引发严重的写入放大问题,导致将固态硬盘的寿命从原来的几年降低为几个月。

  • everysec 【推荐】

说明:每秒执行一次同步显式的将多个写命令同步到磁盘

解释:为了兼顾数据安全和写入性能,用户可以考虑使用everysec选项,让redis每秒一次的频率对AOF文件进行同步;redis每秒同步一次AOF文件时性能和不使用任何持久化特性时的性能相差无几,而通过每秒同步一次AOF文件,redis可以保证,即使系统崩溃,用户最多丢失一秒之内产生的数据。

  • no 【不推荐】

说明:由操作系统决定何时同步

解释:最后使用no选项,将完全有操作系统决定什么时候同步AOF日志文件,这个选项不会对redis性能带来影响但是系统崩溃时,会丢失不定数量的数据,另外如果用户硬盘处理写入操作不够快的话,当缓冲区被等待写入硬盘数据填满时,redis会处于阻塞状态,并导致redis的处理命令请求的速度变慢。

4. AOF重写

1. AOF重写出现的原因

  AOF会导致持久化文件越来越大。例如调用incr test(string插入)命令100次,文件中必须保存全部的100条命令,其实有99条都是多余的。因为要恢复数据库的最后数据状态其实文件中保存一条set test 100就够了。为了压缩aof的持久化文件Redis提供了AOF重写(ReWriter)机制。

2. 配置重写策略
# 1.客户端方式触发重写
执行BGREWRITEAOF命令(不会阻塞redis的服务)

# 2.服务器配置方式自动触发
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
配置语义:auto-aof-rewrite-percentage值为100和auto-aof-rewrite-min-size 64mb,并且启用的AOF持久化时,那么当AOF文件体积大于64M,并且AOF文件的体积比上一次重写之后体积大了至少一倍(100%)时,会自动触发,如果重写过于频繁,用户可以考虑将auto-aof-rewrite-percentage设置为更大
3. 重写原理

注意:重写aof文件的操作,并没有读取旧的aof文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的aof文件,替换原有的文件这点和快照有点类似。

重写步骤

  1. redis服务fork出一个子进程,子进程根据内存数据现状生成数据快照,往临时文件中写入重建数据库状态的命令
  2. 父进程继续处理client请求,除了把写命令写入到原来的aof文件中。同时把收到的写命令缓存起来。这样就能保证如果子进程重写失败的话并不会出问题。
  3. 当子进程把快照内容写入已命令方式写到临时文件中后,子进程发信号通知父进程。然后父进程把缓存的写命令也写入到临时文件。
  4. 现在父进程可以使用临时文件替换老的aof文件,并重命名,后面收到的写命令也开始往新的aof文件中追加。


持久化机制总结

  两种持久化方案既可以同时使用,又可以单独使用,在某种情况下也可以都不使用,具体使用那种持久化方案取决于用户的数据和应用决定。

  无论使用AOF还是RDB持久化,将数据持久化到硬盘都是有必要的,除了持久化外,用户还应该对持久化的文件进行备份(最好备份在多个不同地方)。

2、事物机制

Redis的事务机制-张维鹏:https://blog.csdn.net/a745233700/article/details/113362533

四、redis服务架构

Redis集群原理详解-张维鹏:https://blog.csdn.net/a745233700/article/details/112691126

1、主从复制模式

Redis主从复制原理:https://blog.csdn.net/a745233700/article/details/112404218

作用:主从复制架构仅仅用来解决数据的冗余备份,从节点仅仅用来同步数据

缺点: master节点故障时没有做自动故障转移,无法解决单点压力的问题

  • 搭建
# 修改配置文件
master
	port 6379
	bind 0.0.0.0
	
slave1
	port 6380
	bind 0.0.0.0
	slaveof <masterip> <masterport>

slave2
	port 6381
	bind 0.0.0.0
	slaveof <masterip> <masterport>

# 启动测试
cd /usr/redis/bin
./redis-server /root/master/redis.conf
./redis-server /root/slave1/redis.conf
./redis-server /root/slave2/redis.conf

2、Redis哨兵模式

Redis哨兵机制原理详解-张维鹏:https://blog.csdn.net/a745233700/article/details/112451629

  Sentinel(哨兵)是Redis 的高可用性解决方案:由一个或多个Sentinel 实例 组成的Sentinel 系统可以监视任意多个redis节点,在监视到主节点因故障下线时,自动将该主节点下的某个从节点升级为新的主节点。简单的说哨兵就是带有自动故障转移功能的主从架构

无法解决:

  1. 单节点并发压力问题
  2. 单节点内存和磁盘物理上限

  • 搭建

https://blog.csdn.net/weixin_43260238/article/details/125488290

  • springboot连接哨兵
# redis sentinel 配置
# master书写是使用哨兵监听的那个名称
spring.redis.sentinel.master=mymaster
# 连接的不再是一个具体redis主机,而是多个哨兵节点地址
spring.redis.sentinel.nodes=192.168.202.206:26379,192.168.202.207:26379,....
  • 注意:如果连接过程中出现如下错误:RedisConnectionException: DENIED Redis is running in protected mode because protected mode is enabled, no bind address was specified, no authentication password is requested to clients. In this mode connections are only accepted from the loopback interface. If you want to connect from external computers to Redis you may adopt one of the following solutions: 1) Just disable protected mode sending the command ‘CONFIG SET protected-mode no’ from the loopback interface by connecting to Redis from the same host the server is running, however MAKE SURE Redis is not publicly accessible from internet if you do so. Use CONFIG REWRITE to make this change permanent. 2)
  • 解决方案:在哨兵的配置文件中加入bind 0.0.0.0 开启远程连接权限

3、Redis集群模式

  Redis在3.0后开始支持Cluster(模式)模式,目前redis的集群支持节点的自动发现,支持slave-master选举和容错,支持在线分片(sharding shard )等特性。

img

  • 集群节点间通信

  所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽,节点的故障宕机是通过集群中超过半数的节点检测确认为故障时才生效,客户端与redis节点直连,不需要中间proxy层,客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可,redis-cluster把数据插槽(slot)总共[0-16383]映射到所有的物理节点上,cluster负责维护node,node维护slot,slot维护value

集群搭建

  判断一个是集群中的某个节点是否可用需要主节点投票确认,如果半数以上的节点认为当前节点挂掉,那么当前节点就是挂了,所以搭建redis集群时建议节点数最好为奇数,搭建集群至少需要三个主节点,三个从节点,共计6个节点

1.环境准备

# 1.准备环境安装ruby以及redis集群依赖
yum install -y ruby rubygems
gem install redis-xxx.gem

# 2.在一台机器创建7个目录

# 3.每个目录复制一份配置文件
[root@localhost ~]# cp redis-4.0.10/redis.conf 7000/
[root@localhost ~]# cp redis-4.0.10/redis.conf 7001/
[root@localhost ~]# cp redis-4.0.10/redis.conf 7002/
[root@localhost ~]# cp redis-4.0.10/redis.conf 7003/
[root@localhost ~]# cp redis-4.0.10/redis.conf 7004/
[root@localhost ~]# cp redis-4.0.10/redis.conf 7005/
[root@localhost ~]# cp redis-4.0.10/redis.conf 7006/

# 4.修改不同目录配置文件
port 	6379 .....                		 # 修改端口
bind  0.0.0.0                   		 # 开启远程连接
cluster-enabled  yes 	        		 # 开启集群模式
cluster-config-file  nodes-port.conf	 # 集群节点配置文件
cluster-node-timeout  5000      	     # 集群节点超时时间
appendonly  yes   		             	 # 开启AOF持久化

# 5.指定不同目录配置文件启动七个节点
[root@localhost bin]# ./redis-server  /root/7000/redis.conf
[root@localhost bin]# ./redis-server  /root/7001/redis.conf
[root@localhost bin]# ./redis-server  /root/7002/redis.conf
[root@localhost bin]# ./redis-server  /root/7003/redis.conf
[root@localhost bin]# ./redis-server  /root/7004/redis.conf
[root@localhost bin]# ./redis-server  /root/7005/redis.conf
[root@localhost bin]# ./redis-server  /root/7006/redis.conf

# 6.查看进程
[root@localhost bin]# ps aux|grep redis

2.创建集群

# 1.复制集群操作脚本到bin目录中
[root@localhost bin]# cp /root/redis-4.0.10/src/redis-trib.rb .

# 2.创建集群
./redis-trib.rb create --replicas 1 192.168.202.205:7000 192.168.202.205:7001 192.168.202.205:7002 192.168.202.205:7003 192.168.202.205:7004 192.168.202.205:7005

创建成功出现如下提示

2.查看集群状态

# 1.查看集群状态
./redis-trib.rb check
./redis-trib.rb check 192.168.202.205:7000

# 2.集群节点状态说明
主节点 
	主节点存在hash slots,且主节点的hash slots 没有交叉
	主节点不能删除
	一个主节点可以有多个从节点
	主节点宕机时多个副本之间自动选举主节点

从节点
	从节点没有hash slots
	从节点可以删除
	从节点不负责数据的写,只负责数据的同步

3.添加主节点

# 1.添加主节点 add-node [新加入节点] [原始集群中任意节点]
./redis-trib.rb  add-node 192.168.1.158:7006  192.168.1.158:7005
注意:
	1.该节点必须以集群模式启动
	2.默认情况下该节点就是以master节点形式添加

4.添加从节点

# 1.添加从节点 add-node --slave [新加入节点] [集群中任意节点]
# 注意:当添加副本节点时没有指定主节点,redis会随机给副本节点较少的主节点添加当前副本节点
./redis-trib.rb  add-node --slave 192.168.1.158:7006 192.168.1.158:7000

# 2.为确定的master节点添加副本节点 add-node --slave --master-id master节点id [新加入节点] [集群任意节点]
./redis-trib.rb  add-node --slave --master-id 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 127.0.0.1:7006  127.0.0.1:7000

5.删除副本节点

# 1.删除节点 del-node [集群中任意节点] [删除节点id]
./redis-trib.rb  del-node 127.0.0.1:7002 0ca3f102ecf0c888fc7a7ce43a13e9be9f6d3dd1
注意:
 1.被删除的节点必须是从节点或没有被分配hash slots的节点

6.集群在线分片

# 1.在线分片 reshard [集群中任意节点] [无]
./redis-trib.rb  reshard  192.168.1.158:7000

五、问题

六、使用场景

1、分布式锁

https://www.cnblogs.com/hhddd-1024/p/16985137.html

2、Geo查找附近位置

https://segmentfault.com/a/1190000022973461

3、分布式Session会话

开源的分布式会话组件:https://gitee.com/dromara/sa-token

  使用redis管理session数据是利用spring提供的session管理解决方案,将一个应用session交给Redis存储,整个应用中所有session的请求都会去redis中获取对应的session数据。

spring整合

  • 引入依赖
<dependency>
  <groupId>org.springframework.session</groupId>
  <artifactId>spring-session-data-redis</artifactId>
</dependency>
1234
  • 开发Session管理配置类
@Configuration
@EnableRedisHttpSession
public class RedisSessionManager {
}
12345
  • 打包测试

参考

https://www.cnblogs.com/l-y-h/category/1491835.html

posted @ 2021-02-28 23:32  黄河大道东  阅读(81)  评论(0编辑  收藏  举报