我用一天时间爆肝出了这份Redis详细笔记

一、NoSQL

1.1、NoSQL引言

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

1.2、为什么是NoSQL

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

1.3、NoSQL的四大分类

1.3.1、键值(Key-Value)存储数据库

1.3.1.1、说明

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

1.3.1.2、特点

  1. Key/value模型对于IT系统来说的优势在于简单、易部署。
  2. 如果DBA只对部分值进行查询或更新的时候,Key/value就显得效率低下了。

1.3.1.3、相关产品

  1. Tokyo Cabinet/Tyrant,
  2. Redis
  3. SSDB
  4. Voldemort
  5. Oracle BDB

1.3.2、列存储数据库

1.3.2.1、说明

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

1.3.2.2、特点

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

1.3.2.3、相关产品

  1. Cassandra
  2. HBase
  3. Riak.

1.3.3、文档型数据库

1.3.3.1、说明

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

1.3.3.2、特点

    以文档形式存储。

1.3.3.3、相关产品

  1. MongoDB
  2. CouchDB
  3. MongoDb(4.x)
  4. SequoiaDB(国内)

1.3.4、图形(Graph)数据库

1.3.4.1、特点

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

1.3.4.2、相关产品

  1. Neo4J
  2. InfoGrid
  3. Infinite Graph

1.4、NoSQL应用场景

  • 数据模型比较简单

  • 需要灵活性更强的IT系统

  • 对数据库性能要求较高

  • 不需要高度的数据一致性

二、Redis入门

2.1、概述

我用一天时间爆肝出了这份Redis详细笔记_第1张图片

redis是一个内存型的数据库

2.2、Redis特点

  1. Redis是一个高性能key/value内存型数据库。

  2. Redis支持丰富的数据类型 。

  3. Redis支持持久化 。

  4. Redis单线程,单进程。

2.3、Redis的安装(Linux版)

2.3.1、下载Redis源码包

下载地址直达

我用一天时间爆肝出了这份Redis详细笔记_第2张图片

2.3.2、上传并解压

tar -zxvf redis-4.0.10.tar.gz

image-20200623124522026

2.3.3、安装gcc

 yum install -y gcc

2.3.4、进入解压缩目录

make MALLOC=libc

2.3.5、编译完成后执行如下命令

make install PREFIX=/usr/redis

2.3.6、进入/usr/redis目录启动redis服务

./redis-server

我用一天时间爆肝出了这份Redis详细笔记_第3张图片

    一旦出现这个页面就代表Redis启动了!

2.3.7、进入bin目录执行客户端连接操作

./redis-cli –p 6379        (终端不展示中文)
/redis-cli –p 6379 --raw  (终端展示中文)

2.4、Redis安装的细节

redis启动服务的 细节

    如果直接使用./redis-server方式启动使用的是redis-server这个shell设置,我们在启动的时候,要先启动服务器 ./redis-server 然后克隆窗口(不可以按ctrl+c暂停),在新窗口中启动客户端 ./redis-cli –p 6379

如何在启动redis时指定配置文件启动

    默认在reidis安装完成之后在安装目录没有任何配置文件,需要在源码目录中复制redis.conf配置文件到安装目录,具体操作:

  1. 进入源码目录,复制文件
cp redis.conf /usr/redis
  1. 进入/usr/redis的安装目录查看复制配置文件
 cd /usr/redis
 ls
  1. 进入bin目录加载配置启动
./redis-server ../redis.conf

redis中库的概念

    库是database 用来存放数据的一个基本单元,一个库可以存放key-value键值对,redis中每一个库都有一个唯一名称(编号),从0开始,默认库的个数是16个库,库的编号0-15,默认使用的是0号库。
    我们可以使用命令来切换库,每个库是相互隔离的,每个库都可以有相同或者不同的key和value,互不影响。

# 切换库
select dbid(库编号)
# 清空当前库
flushDB   
# 清空所有库 
flushAll 

开启Redis远程连接

  1. 修改配置文件开启远程连接
vim redis.conf
  1. 修改配置,按两下键盘上的g到文章的第一个字母,然后在ntework章节中找到bind属性,默认:bing 127.0.0.1 只允许本机访问,修改为:
# 允许一切客户端访问
bing 0.0.0.0 
  1. 以配置文件的方式重启Redis
./redis-server ../redis.conf
  1. 可以在客户端中关闭Redis
# (切记前面有一个空格)
hutdown

三、Redis数据库相关指令

3.1、数据库操作指令

3.1.1、库的说明

    Rsdis默认配置器动Redis服务后,默认会存在16个库,编号从0-15,可以使用select 库的编号,来选择一个Rsdis的库。

seelect 库编号

3.1.2、清空库

# 清空当前的库 
FLUSHDB
# 清空全部的库 
FLUSHALL

3.1.3、redis客户端显示中文

./redis-cli  -p 7000 --raw

3.2、操作key的相关指令

3.2.1、DEL指令

3.2.1.1、语法

 DEL key [key ...] 

3.2.1.2、作用

    删除给定的一个或多个key 。不存在的key 会被忽略。

3.2.1.3、返回值

    被删除key的数量。

3.2.2、EXISTS指令

3.2.2.1、语法

EXISTS key

3.2.2.2、作用

    检查给定key是否存在。

3.2.2.3、返回值

    若key 存在,返回1 ,否则返回0。

3.2.3、EXPIRE指令

3.2.3.1、语法

EXPIRE key seconds

3.2.3.2、作用

    为给定key设置生存时间,当key 过期时(生存时间为0 ),它会被自动删除。他的时间复杂度为O(1)。

3.2.3.3、返回值

    设置成功返回1。

3.2.4、PEXPIRE指令

3.2.4.1、语法

PEXPIRE key milliseconds

3.2.4.2、作用

    这个命令和EXPIRE 命令的作用类似,但是它以毫秒为单位设置key 的生存时间,而不像EXPIRE 命令那样,以秒为单位。他的时间复杂度也是 O(1)

3.2.4.3、返回值

    设置成功,返回1 key 不存在或设置失败,返回0

3.2.5、KEYS指令

3.2.5.1、语法

KEYS pattern

    他的pattern是一种通配符,可以进行匹配:

  1. KEYS * :匹配数据库中所有key 。
  2. KEYS h?llo:匹配hello ,hallo 和hxllo 等。
  3. KEYS h*llo:匹配hllo 和heeeeello 等。
  4. KEYS h[ae]llo:匹配hello 和hallo ,但不匹配hillo 。特殊符号用 "\"隔开。

3.2.5.2、作用

    查找所有符合给定模式pattern 的key 。

3.2.5.3、返回值

    符合给定模式的key列表。

3.2.6、MOVE指令

3.2.6.1、语法

MOVE key db

3.2.6.2、作用

    将当前数据库的key 移动到给定的数据库db 当中。

3.2.6.3、返回值

    移动成功返回1 ,失败则返回0

3.2.7、TTL指令

3.2.7.1、语法

 TTL key

3.2.7.2、作用

以秒为单位,返回给定key 的剩余生存时间(TTL, time to live)。

3.2.7.3、返回值

  1. 当key 不存在时,返回-2 。
  2. 当key 存在但没有设置剩余生存时间时,返回-1 。
  3. 否则,以秒为单位,返回key 的剩余生存时间。
  4. 在Redis 2.8 以前,当key 不存在,或者key 没有设置剩余生存时间时,命令都返回-1 。

3.2.8、PTTL指令

3.2.8.1、语法

PTTL key

3.2.8.2、作用

     这个命令类似于TTL 命令,但它以毫秒为单位返回key 的剩余生存时间,而不是像TTL 命令那样,以秒为单位。

3.2.8.3、返回值

  1. 当key 不存在时,返回-2 。当key 存在但没有设置剩余生存时间时,返回-1 。
  2. 否则,以毫秒为单位,返回key 的剩余生存时间。
  3. 在Redis 2.8 以前,当key 不存在,或者key 没有设置剩余生存时间时,命令都返回-1 。

3.2.9、RANDOMKEY指令

3.2.9.1、语法

RANDOMKEY

3.2.9.2、作用

    从当前数据库中随机返回(不删除) 一个key 。

3.2.9.3、返回值

    当数据库不为空时,返回一个key 。当数据库为空时,返回nil 。

3.2.10、RENAME指令

3.2.10.1、语法

RENAME key newkey

3.2.10.2、作用

    将key 改名为newkey 。当key 和newkey 相同,或者key 不存在时,返回一个错误。当newkey 已经存在时,RENAME 命令将覆盖旧值。

3.2.10.3、返回值

    改名成功时提示OK ,失败时候返回一个错误。

3.2.11、TYPE指令

3.2.11.1、语法
TYPE key

3.2.11.2、作用

返回key 所储存的值的类型。

3.2.11.3、返回值

  1. none (key 不存在)
  2. string (字符串)
  3. list (列表)
  4. set (集合)
  5. zset (有序集)
  6. hash (哈希表)

四、Redis中的数据类型

4.1、String类型

4.1.1、内存模型

我用一天时间爆肝出了这份Redis详细笔记_第4张图片

4.1.2、常用操作命令

命令 说明
set 设置一个key/value
get 根据key获得对应的value
mset 一次设置多个key value
mget 一次获得多个key的value
getset 获得原始key的值,同时设置新值
strlen 获得对应key存储value的长度
append 为对应key的value追加内容
getrange 截取value的内容,-1可以代表末尾(索引0开始)
setex 设置一个key存活的有效期(秒)
psetex 设置一个key存活的有效期(毫秒)
setnx 存在不做任何操作,不存在添加
msetnx 可以同时设置多个key,原子操作,只要有一个存在都不保存
decr 进行数值类型的-1操作
decrby 根据提供的数据进行减法操作
Incr 进行数值类型的+1操作
incrby 根据提供的数据进行加法操作
Incrbyfloat 根据提供的数据加入浮点数

4.2、List类型

    Redis中的List类型相当于java中list 集合,他的特点是元素有序且可以重复

4.2.1、内存模型

我用一天时间爆肝出了这份Redis详细笔记_第5张图片

4.2.2、常用操作指令

命令 说明
lpush 将某个值加入到一个key列表头部(从左添加)
lpushx 同lpush,但是必须要保证这个key存在
rpush 将某个值加入到一个key列表末尾(从右边开始放元素)
rpushx 同rpush,但是必须要保证这个key存在
lpop 返回和移除列表左边的第一个元素,并且返回
rpop 返回和移除列表右边的第一个元素,并且返回
lrange 获取某一个下标区间内的元素(遍历,默认从0开始,最后的可以用-1)
llen 获取列表元素个数
lset 设置某一个指定索引的值(索引必须存在)
lindex 获取某一个指定索引位置的元素
lrem 删除重复元素 lerm lists 3 zhangsan(删除lists集合中3个zhangsan)
ltrim 保留列表中特定区间内的元素
linsert 在某一个元素之前,之后插入新元素

4.3、Set类型

4.3.1、内存模型

我用一天时间爆肝出了这份Redis详细笔记_第6张图片

4.3.2、常用命令

命令 说明
sadd 为集合添加元素
smembers 显示集合中所有元素,实际上是无序
scard 返回集合中元素的个数
spop 随机返回一个元素 并将元素在集合中删除
smove 从一个集合中向另一个集合移动元素 ,必须是同一种类型
srem 从集合中删除一个元素
sismember 判断一个集合中是否含有这个元素
srandmember 随机返回元素
sdiff 去掉第一个集合中其它集合含有的相同元素
sinter 求交集
sunion 求和集

4.4、ZSet类型

    他是一个可排序的set集合 且不可重复 ,又称作sortSet 。

4.4.1、内存模型

我用一天时间爆肝出了这份Redis详细笔记_第7张图片

4.4.2、常用命令

命令 说明
zadd 添加一个有序集合元素
zcard 返回集合的元素个数
zrange 升序 zrevrange 降序 返回一个范围内的元素
zrangebyscore 按照分数查找一个范围内的元素
zrank 返回排名
zrevrank 倒序排名
zscore 显示某一个元素的分数
zrem 移除某一个元素
zincrby 给某个特定元素加分

4.5、Hash类型

     value中放一个map结构,存在key和value,key是无序的

4.5.1、内存模型

我用一天时间爆肝出了这份Redis详细笔记_第8张图片

4.5.2、常用命令

命令 说明
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 为value进行加法运算(实现自增)
hincrbyfloat 为value加入浮点值(最多保留17位)

五、持久化机制

    所谓的持久化就是将内存中的数据转移到磁盘,Redis提供了两种持久化机制:

  1. 快照(Snapshot)
  2. AOF (Append Only File) 只追加日志文件

5.1、RDB(快照)

5.1.1、特点

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

5.1.2、生成快照的方式

5.1.2.1、客户端指令方式

    客户端有两种指令可以生成快照:BGSAVE指令和SAVE指令。

5.1.2.1.1、BGSAVE(后台创建快照)

    客户端可以使用BGSAVE命令来创建一个快照,当接收到客户端的BGSAVE命令时,redis会调用fork操作来创建一个子进程,然后子进程负责将快照写入磁盘中,而父进程则继续处理命令请求。
    fork是操作一个进程创建子进程的时候,底层的操作系统会创建该进程的一个副本,在类unix系统中创建子进程的操作会进行优化:在刚开始的时候,父子进程共享相同内存,直到父进程或子进程对内存进行了写之后,对被写入的内存的共享才会结束服务。他的优势是不会阻塞服务器,同时还可以保证快照的创建。

    简单来说就是ork 出一个子进程,子进程负责调用rdbSave ,并在保存完成之后向主进程发送信号,通知保存已完成。因为rdbSave 在子进程被调用,所以Redis 服务器在BGSAVE 执行期间仍然可以继续处理客户端的请求。

我用一天时间爆肝出了这份Redis详细笔记_第9张图片

5.1.2.1.2、SAVE

    客户端还可以使用SAVE命令来创建一个快照,接收到SAVE命令的redis服务器直接调用rdbSave,阻塞Redis主进程看,直到保存完成为止。在主进程阻塞期间,服务器不能处理客户端的任何请求。

    SAVE命令并不常用,使用SAVE命令在快照创建完毕之前,redis处于阻塞状态,无法对外服务

我用一天时间爆肝出了这份Redis详细笔记_第10张图片

5.1.2.2、自动触发

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

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-moggs1lP-1621058295221)(D:\学习笔记\Java高级框架\Redis\Redis.assets\image-20200623210021012.png)]

5.1.3、配置生成快照名称和位置

配置快照生成的名字

dbfilename dump.rdb

修改快照生成的位置

dir ./

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VEDzVXrI-1621058295222)(D:\学习笔记\Java高级框架\Redis\Redis.assets\image-20200623210352448.png)]

5.2、AOF (Append Only File) 只追加日志文件

5.2.1、特点

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

我用一天时间爆肝出了这份Redis详细笔记_第11张图片

5.2.2、开启AOF

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

修改配置文件的appendonly属性

appendonly属性默认是为no,说明默认是不开启的,我们需要将no修改为yes。

修改 appendfilename属性指定指定生成文件名称

我用一天时间爆肝出了这份Redis详细笔记_第12张图片

5.2.3、日志追加频率

5.2.3.1、always(谨慎使用)

    这个属性会将每个redis写命令都要同步写入硬盘,严重降低redis速度,如果用户使用了always选项,那么每个redis写命令都会被写入硬盘,从而将发生系统崩溃时出现的数据丢失减到最少。

    但是因为这种同步策略需要对硬盘进行大量的写入操作,所以redis处理命令的速度会受到硬盘性能的限制。

    转盘式硬盘在这种频率下200左右个命令/s ; 固态硬盘(SSD) 几百万个命令/s。使用SSD用户请谨慎使用always选项,这种模式不断写入少量数据的做法有可能会引发严重的写入放大问题,导致将固态硬盘的寿命从原来的几年降低为几个月。

5.2.3.2、everysec

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

5.2.3.3、no

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

5.2.3.4、配置频率

    修改配置文件中的1appendfsync属性指定everysec、always、no。

image-20200623211658910

5.2.4、重写AOF文件

5.2.4.1、AOF带来的问题

    AOF的方式也同时带来了另一个问题。持久化文件会变的越来越大。例如我们调用incr test命令100次,文件中必须保存全部的100条命令,其实有99条都是多余的。因为要恢复数据库的状态其实文件中保存一条set test 100就够了。为了压缩aof的持久化文件,Redis提供了AOF重写(ReWriter)机制。
    这个机制可以在一定程度上减小AOF文件的体积。

5.2.4.2、配置重写方式

配置redis.conf中的auto-aof-rewrite-percentage选项

我用一天时间爆肝出了这份Redis详细笔记_第13张图片

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

5.2.4.3、重写原理

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

    重写的流程:

  1. Redis调用fork生成一个子进程,子进程根据此时的数据库生成快照文件,同时以命令的形式往临时文件中写入重建数据库状态的命令。
  2. 父进程继续处理客户端的请求,除了将执行的命令写入到原来的aof文件中,同时把收到的请求缓存起来,这样就能保证如果子进程重写失败的话,也不会出现数据丢失的情况。
  3. 当子进程把快照的内容以命令的方式写入到临时文件之后,子进程发出信号通知父进程,然后把父进程刚刚缓存的命令也写入到临时文件。
  4. 将新的aof文件替换原来老的aof文件,后面收到的命令也写入到新的aof文件中。

我用一天时间爆肝出了这份Redis详细笔记_第14张图片

六、Java操作Redis

6.1、环境准备

6.1.1、引入依赖


<dependency>
  <groupId>redis.clientsgroupId>
  <artifactId>jedisartifactId>
  <version>2.9.0version>
dependency>

6.1.2、创建jedis对象

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

6.2、操作key相关API

private Jedis jedis;
    @Before
    public void before(){
     
        this.jedis = new Jedis("127.0.0.1", 7000);
    }
    @After
    public void after(){
     
        jedis.close();
    }

    //测试key相关
    @Test
    public void testKeys(){
     
        //删除一个key
        jedis.del("name");
        //删除多个key
        jedis.del("name","age");

        //判断一个key是否存在exits
        Boolean name = jedis.exists("name");
        System.out.println(name);

        //设置一个key超时时间 expire pexpire
        Long age = jedis.expire("age", 100);
        System.out.println(age);

        //获取一个key超时时间 ttl
        Long age1 = jedis.ttl("newage");
        System.out.println(age1);

        //随机获取一个key
        String s = jedis.randomKey();

        //修改key名称
        jedis.rename("age","newage");

        //查看可以对应值的类型
        String name1 = jedis.type("name");
        System.out.println(name1);
        String maps = jedis.type("maps");
        System.out.println(maps);
    }

6.3、操作String相关API

//测试String相关
    @Test
    public void testString(){
     
        //set
        jedis.set("name","xiaolin");
        //get
        String s = jedis.get("name");
        System.out.println(s);
        //mset
        jedis.mset("content","好人","address","海淀区");
        //mget
        List<String> mget = jedis.mget("name", "content", "address");
        mget.forEach(v-> System.out.println("v = " + v));
        //getset
        String set = jedis.getSet("name", "小明");
        System.out.println(set);

        //............
    }

6.4、操作List相关API

//测试List相关
    @Test
    public void testList(){
     

        //lpush
        jedis.lpush("names1","张三","王五","赵柳","win7");

        //rpush
        jedis.rpush("names1","xiaomingming");

        //lrange

        List<String> names1 = jedis.lrange("names1", 0, -1);
        names1.forEach(name-> System.out.println("name = " + name));

        //lpop rpop
        String names11 = jedis.lpop("names1");
        System.out.println(names11);

        //llen
        jedis.linsert("lists", BinaryClient.LIST_POSITION.BEFORE,"xiaohei","xiaobai");

      	//........

    }

6.5、操作Set的相关API

//测试SET相关
@Test
public void testSet(){
     

  //sadd
  jedis.sadd("names","zhangsan","lisi");

  //smembers
  jedis.smembers("names");

  //sismember
  jedis.sismember("names","xiaochen");

  //...
}

6.6、操作ZSet相关API

//测试ZSET相关
@Test
public void testZset(){
     

  //zadd
  jedis.zadd("names",10,"张三");

  //zrange
  jedis.zrange("names",0,-1);

  //zcard
  jedis.zcard("names");

  //zrangeByScore
  jedis.zrangeByScore("names","0","100",0,5);

  //..

}

6.7、操作Hash相关API

//测试HASH相关
@Test
public void testHash(){
     
  //hset
  jedis.hset("maps","name","zhangsan");
  //hget
  jedis.hget("maps","name");
  //hgetall
  jedis.hgetAll("mps");
  //hkeys
  jedis.hkeys("maps");
  //hvals
  jedis.hvals("maps");
  //....
}

七、SpringBoot整合Redis

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

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

7.1、环境准备

7.1.1、引入依赖

<dependency>
  <groupId>org.springframework.bootgroupId>
  <artifactId>spring-boot-starter-data-redisartifactId>
dependency>

7.1.2、配置application.propertie

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

7.2、使用StringRedisTemplate和RedisTemplate

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

    @Test
    public void testRedisTemplate(){
     
        System.out.println(redisTemplate);
        //设置redistemplate值使用对象序列化策略
        redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());//指定值使用对象序列化
        //redisTemplate.opsForValue().set("user",new User("21","小黑",23,new Date()));
        User user = (User) redisTemplate.opsForValue().get("user");
        System.out.println(user);
//      Set keys = redisTemplate.keys("*");
//      keys.forEach(key -> System.out.println(key));
        /*Object name = redisTemplate.opsForValue().get("name");
        System.out.println(name);*/

        //Object xiaohei = redisTemplate.opsForValue().get("xiaohei");
        //System.out.println(xiaohei);
        /*redisTemplate.opsForValue().set("name","xxxx");
        Object name = redisTemplate.opsForValue().get("name");
        System.out.println(name);*/
        /*redisTemplate.opsForList().leftPushAll("lists","xxxx","1111");
        List lists = redisTemplate.opsForList().range("lists", 0, -1);
        lists.forEach(list-> System.out.println(list));*/
    }


    //key的绑定操作 如果日后对某一个key的操作及其频繁,可以将这个key绑定到对应redistemplate中,日后基于绑定操作都是操作这个key
    //boundValueOps 用来对String值绑定key
    //boundListOps 用来对List值绑定key
    //boundSetOps 用来对Set值绑定key
    //boundZsetOps 用来对Zset值绑定key
    //boundHashOps 用来对Hash值绑定key

    @Test
    public void testBoundKey(){
     
        BoundValueOperations<String, String> nameValueOperations = stringRedisTemplate.boundValueOps("name");
        nameValueOperations.set("1");
        //yuew
        nameValueOperations.set("2");
        String s = nameValueOperations.get();
        System.out.println(s);

    }


    //hash相关操作 opsForHash
    @Test
    public void testHash(){
     
        stringRedisTemplate.opsForHash().put("maps","name","小黑");
        Object o = stringRedisTemplate.opsForHash().get("maps", "name");
        System.out.println(o);
    }

    //zset相关操作 opsForZSet
    @Test
    public void testZSet(){
     
        stringRedisTemplate.opsForZSet().add("zsets","小黑",10);
        Set<String> zsets = stringRedisTemplate.opsForZSet().range("zsets", 0, -1);
        zsets.forEach(value-> System.out.println(value));
    }

    //set相关操作 opsForSet
    @Test
    public void testSet(){
     
        stringRedisTemplate.opsForSet().add("sets","xiaosan","xiaosi","xiaowu");
        Set<String> sets = stringRedisTemplate.opsForSet().members("sets");
        sets.forEach(value-> System.out.println(value));
    }

    //list相关的操作opsForList
    @Test
    public void testList(){
     
        // stringRedisTemplate.opsForList().leftPushAll("lists","张三","李四","王五");
        List<String> lists = stringRedisTemplate.opsForList().range("lists", 0, -1);
        lists.forEach(key -> System.out.println(key));
    }


    //String相关的操作 opsForValue
    @Test
    public void testString(){
     
        //stringRedisTemplate.opsForValue().set("166","好同学");
        String s = stringRedisTemplate.opsForValue().get("166");
        System.out.println(s);
        Long size = stringRedisTemplate.opsForValue().size("166");
        System.out.println(size);
    }


    //key相关的操作
    @Test
    public void test(){
     
        Set<String> keys = stringRedisTemplate.keys("*");//查看所有key
        Boolean name = stringRedisTemplate.hasKey("name");//判断某个key是否存在
        stringRedisTemplate.delete("age");//根据指定key删除
        stringRedisTemplate.rename("","");//修改key的名称
        stringRedisTemplate.expire("key",10, TimeUnit.HOURS);
      	//设置key超时时间 参数1:设置key名 参数2:时间 参数3:时间的单位
        stringRedisTemplate.move("",1);//移动key
    }

7.3、springboot操作redis总结

​ 1. 针对日后处理keyvalue都是String时使用StringRedisTemplate

​ 2. 针对日后处理keyvalue时存在对象用RedisTempLate

​ 3. 针对于同一个key多次操作可以使用**boundXxxOps()**的api简化书写

7.4、Redis应用场景

  1. 利用redis字符串类型完成项目手机验证码存储的实现
  2. 利用redis字符串类型完成具有实效性业务功能:比如说淘宝订单还要40分钟就关闭
  3. 利用redis分布式集群系统中Session共享,以前时用memcahe(内存型)来完成的,但是memcache数据存储有上限,数据类型比较单一
  4. 利用redis的zset类型(可排序的set类型),利用元素的分数完成排行榜之类的功能
  5. 利用redis分布式缓存
  6. 利用redis存储认证后token信息
  7. 利用redis解决分布式集群系统中分布式锁的问题

八、Redis分布式缓存

8.1、什么是缓存

    缓存就是计算机内存中的一段数据.
    他有两个特点:

  1. 读写快.
  2. 断电立即丢失.

8.2、缓存需要解决的问题

  1. 提高网站的吞吐量,提高了网站运行效率.
  2. 缓存的存在是为了在一定程度上减轻了数据库的访问压力.

8.3、误区

    虽然缓存能够提高效率,但是并不是项目中的所有数据都加入到缓存中,因为你的内存不够那么大,内存会爆.使用缓存时一定是数据库中极少发生修改的,更多用于查询这种情况,例如:当当网地址的省份 信息

8.4、本地缓存和分布式缓存区别

  1. 本地缓存:存在应用服务器内存中的数据称为本地缓存(local cache).
  2. 分布式缓存:存储在当前应用服务器内存之外的数据成为分布式缓存(distribute cache).
  3. 集群:将同一种服务的多个节点放在一起共同对系统提供服务称之为集群.
  4. 分布式:多个不同的服务集群共同对系统提供服务的,这个系统称之为分布式系统,分布式一定是在集群的基础上(distribute system)

九、Redis的主从复制

9.1、主从复制概述

    主从复制架构仅仅用来解决数据的 冗余备份,从节点仅仅用来同步数据,他无法解决master节点出现故障的自动故障转移。

我用一天时间爆肝出了这份Redis详细笔记_第15张图片

9.2、主从复制搭建

我们需要准备三台Redis,这里我开三台虚拟机举例子。修改redis.conf配置文件

主节点:

- master
	port 6379
	bind 0.0.0.0

从节点1:

- slave1
	port 6380
	bind 0.0.0.0
	slaveof masterip masterport

从节点2:

- slave2
	port 6381
	bind 0.0.0.0
	slaveof masterip masterport

image-20200627202443388

以配置文件的形式启动三台服务器:

./redis-server /root/master/redis.conf
./redis-server /root/slave1/redis.conf
./redis-server /root/slave2/redis.conf

十、哨兵机制

    Sentinel(哨兵)是Redis 的高可用性解决方案:由一个或多个Sentinel 实例 组成的Sentinel 系统可以监视任意多个主服务器,以及这些主服务器属下的所有从服务器,并在被监视的主服务器进入下线状态时,自动将下线主服务器属下的某个从服务器升级为新的主服务器。简单的说哨兵就是带有自动故障转移功能的主从架构

他也有无法解决的问题:

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

我用一天时间爆肝出了这份Redis详细笔记_第16张图片

10.1、搭建哨兵架构

10.1.1、在主节点上创建哨兵配置

在Master对应redis.conf同目录下新建sentinel.conf文件,名字绝对不能错;

10.1.2、配置哨兵

在sentinel.conf文件中填入内容:

 sentinel monitor 被监控数据库名字(自己起名字) ip port 1

10.1.3、启动哨兵测试

redis-sentinel  /root/sentinel/sentinel.conf

你可能感兴趣的:(教学,数据库,分布式,redis,java)