redis

1. NoSQL 数据库简介

1.1. 技术发展

技术的分类

  1. 解决功能性的问题:Java、Jsp、RDBMS、Tomcat、HTML、Linux、JDBC、SVN
  2. 解决扩展性的问题:Struts、Spring、SpringMVC、Hibernate、Mybatis
  3. 解决性能的问题:NoSQL、Java 线程、Hadoop、Nginx、MQ、ElasticSearch

1.1.1. Web1.0 时代

​ Web1.0 的时代,数据访问量很有限,用一夫当关的高性能的单点服务器可以 解决大部分问题。

image-20220518173158243

1.1.2. Web2.0 时代

​ 随着 Web2.0 的时代的到来,用户访问量大幅度提升,同时产生了大量的用户 数据。加上后来的智能移动设备的普及,所有的互联网平台都面临了巨大的性能挑 战

image-20220518173251617

1.1.3. 解决 CPU 及内存压力

image-20220518173325299

1.1.4. 解决 IO 压力

image-20220518173346554

1.2. NoSQL 数据库

1.2.1. NoSQL 数据库概述

NoSQL(NoSQL = Not Only SQL ),意即“不仅仅是 SQL”,泛指非关系型的数据 库

NoSQL 不依赖业务逻辑方式存储,而以简单的 key-value 模式存储。因此大大的增加了 数据库的扩展能力。

  • 不遵循 SQL 标准。
  • 不支持 ACID。
  • 远超于 SQL 的性能。

1.2.2. NoSQL 适用场景

  • 对数据高并发的读写
  • 海量数据的读写
  • 对数据高可扩展性的

1.2.3. NoSQL 不适用场景

  • 需要事务支持
  • 基于 sql 的结构化查询存储,处理复杂的关系,需要即席查询。
  • (用不着 sql 的和用了 sql 也不行的情况,请考虑用 NoSql)

image-20220518174106374

1.3. 行式存储数据库(大数据时代)

1.3.1. 行式数据库

image-20220518174155163

2. Redis 概述安装

  • Redis 是一个开源的 key-value 存储系统。
  • 和 Memcached 类似,它支持存储的 value 类型相对更多,包括 string(字符串)、 list(链表)、 set(集合)、 zset(sorted set --有序集合)和 hash(哈希类型)。 ➢
  • 这些数据类型都支持 push/pop、add/remove 及取交集并集和差集及更丰富的操 作,而且这些操作都是 原子性的。 ➢
  • 在此基础上,Redis 支持各种不同方式的排序。
  • 与 memcached 一样,为了保证效率,数据都是缓存在 内存中
  • 区别的是 Redis 会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记 录文件。
  • 并且在此基础上实现了 master-slave(主从)同步。

2.1. 应用场景

2.1.1. 配合关系型数据库做高速缓存

高频次,热门访问的数据,降低数据库 IO

分布式架构,做 session 共享

image-20220518175232924

2.1.2. 多样的数据结构存储持久化数据

image-20220518175326704

2.2. Redis 安装

Redis 官方网站Redis 中文官方网站
http://redis.iohttp://redis.cn/

image-20220518175435576image-20220518175457028

2.2.1. 安装版本

6.2.1 for Linux(redis-6.2.1.tar.gz)

不用考虑在 windows 环境下对 Redis 的支持

image-20220518175812818

2.2.2. 安装步骤

2.2.2.1. 准备工作:下载安装最新版的 gcc 编译器

安装 C 语言的编译环境

yum install centos-release-scl scl-utils-build

yum install -y devtoolset-8-toolchain

scl enable devtoolset-8 bash

测试 gcc 版本

gcc --version

image-20220518180039129

2.2.2.2. 下载 redis-6.2.1.tar.gz 放/opt 目录
2.2.2.3. 解压命令:tar -zxvf redis-6.2.1.tar.gz
2.2.2.4. 解压完成后进入目录:cd redis-6.2.1
2.2.2.5. 在 redis-6.2.1 目录下再次执行 make 命令(只是 编译好)
2.2.2.6. 如果没有准备好 C 语言编译环境,make 会报错— Jemalloc/jemalloc.h:没有那个文件

image-20220519094355236

2.2.2.7. 解决方案:运行 make distclean

image-20220519094433926

2.2.2.8. 在 redis-6.2.1 目录下再次执行 make 命令(只是 编译好)

image-20220519094504573

2.2.2.9. 跳过 make test 继续执行: make install

image-20220519094535616

2.2.3. 安装目录:/usr/local/bin

查看默认安装目录:

redis-benchmark:性能测试工具,可以在自己本子运行,看看自己本子性能如何

redis-check-aof:修复有问题的 AOF 文件,rdb 和 aof 后面讲

redis-check-dump:修复有问题的 dump.rdb 文件

redis-sentinel:Redis 集群使用

redis-server:Redis 服务器启动命令

redis-cli:客户端,操作入口

2.2.4. 前台启动(不推荐)

前台启动,命令行窗口不能关闭,否则服务器停止

image-20220519094800492

2.2.5. 后台启动(推荐)

2.2.5.1.备份 redis.conf

拷贝一份 redis.conf 到其他目录

cp /opt/redis-3.2.5/redis.conf /myredis

2.2.5.2.后台启动设置 daemonize no 改成 yes

修改 redis.conf(128 行)文件将里面的 daemonize no 改成 yes,让服务在后台启动

2.2.5.3.Redis 启动

redis-server/myredis/redis.conf

image-20220519095204983

2.2.5.4.用客户端访问:redis-cli

image-20220519095242042

2.2.5.5.多个端口可以:redis-cli -p6379
2.2.5.6.测试验证: ping

image-20220519095339564

2.2.5.7.Redis 关闭

单实例关闭:redis-cli shutdown

image-20220519095718048

也可以进入终端后再关闭

image-20220519095749450

多实例关闭,指定端口关闭:redis-cli -p 6379 shutdown

2.2.6. Redis 介绍相关知识

3. 常用五大数据类型

image-20220519100049475

Redis 是单线程+多路 IO 复用技术

多路复用是指使用一个线程来检查多个文件描述符(Socket)的就绪状态,比如调用 select 和 poll 函数,传入多个文件描述符,如果有一个文件描述符就绪,则返回,否则 阻塞直到超时。得到就绪状态后进行真正的操作可以在同一个线程里执行,也可以启 动线程执行(比如使用线程池)

(与 Memcache 三点不同: 支持多数据类型,支持持久化,单线程+多路 IO 复用)

image-20220519100327470

哪里去获得 redis 常见数据类型操作命令 http://www.redis.cn/commands.html

3.1. Redis 键(key)

keys *查看当前库所有 key (匹配:keys *1)

exists key 判断某个 key 是否存在

type key 查看你的 key 是什么类型 del key 删除指定的 key 数据

unlink key 根据 value 选择非阻塞删除 仅将 keys 从 keyspace 元数据中删除,真正的删除会在后续异步操作。

expire key 10 10 秒钟:为给定的 key 设置过期时间

ttl key 查看还有多少秒过期,-1 表示永不过期,-2 表示已过期

select 命令切换数据库

dbsize 查看当前数据库的 key 的数量

flushdb 清空当前库

flushall 通杀全部库

3.2. Redis 字符串(String)

3.2.1. 简介

String 是 Redis 最基本的类型,你可以理解成与 Memcached 一模一样的类型,一个 key 对应一个 value。

String 类型是二进制安全的。意味着 Redis 的 string 可以包含任何数据。比如 jpg 图片 或者序列化的对象。

String 类型是 Redis 最基本的数据类型,一个 Redis 中字符串 value 最多可以是 512M

3.2.2. 常用命令

set <key><value>添加键值对

image-20220519101740178

***NX:当数据库中 key 不存在时,可以将 key-value 添加数据库 **

***XX:当数据库中 key 存在时,可以将 key-value 添加数据库,与 NX 参数互斥 **

***EX:key 的超时秒数 **

*PX:key 的超时毫秒数,与 EX 互斥

get<key>查询对应键值
append <key><value>将给定的<value> 追加到原值的末尾
strlen <key>获得值的长度
setnx <key><value>只有在 key 不存在时 设置 key 的值
incr <key>
将 key 中储存的数字值增 1
只能对数字值操作,如果为空,新增值为 1
decr <key>
将 key 中储存的数字值减 1
只能对数字值操作,如果为空,新增值为-1
incrby / decrby <key><步长>将 key 中储存的数字值增减。自定义步长。

image-20220519102505006

这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切换到另 一个线程)。

(1)在单线程中, 能够在单条指令中完成的操作都可以认为是"原子操作",因为 中断只能发生于指令之间。

(2)在多线程中,不能被其它进程(线程)打断的操作就叫原子操作。 Redis 单命令的原子性主要得益于 Redis 的单线程。 案例: java 中的 i++是否是原子操作?不是 i=0;两个线程分别对 i 进行++100 次,值是多少? 2~2

mset<key1><value1><key2><value2> …
同时设置一个或多个 key-value 对
mget<key1><key2><key3> …
同时获取一个或多个 value
msetnx <key1><value1><key2><value2> …
同时设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在。

原子性,有一个失败则都失败

getrange <key><起始位置><结束位置>

获得值的范围,类似 java 中的 substring,前包,后包

setrange <key><起始位置><value>

用 <value>覆写所储存的字符串值,从<起始位置>开始(索引从 0 开始)。

setex <key><过期时间><value>
设置键值的同时,设置过期时间,单位秒。
getset <key><value>
以新换旧,设置了新值同时获得旧值。

3.2.3. 数据结构

​ String 的数据结构为简单动态字符串(Simple Dynamic String,缩写 SDS)。是可以 修改的字符串,内部结构实现上类似于 Java 的 ArrayList,采用预分配冗余空间的方式 来减少内存的频繁分配.

image-20220519103638878

如图中所示,内部为当前字符串实际分配的空间 capacity 一般要高于实际字符串长度 len。当字符串长度小于 1M 时,扩容都是加倍现有的空间,如果超过 1M,扩容时一次 只会多扩 1M 的空间。需要注意的是字符串最大长度为 512M。

3.3. Redis 列表(List)

3.3.1. 简介

单键多值

Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头 部(左边)或者尾部(右边)。

它的底层实际是个双向链表,对两端的操作性能很高,通过索引下标的操作中间的节 点性能会较差。

3.3.2. 常用命令

lpush/rpush <key><value1><value2><value3> … 从左边/右边插入一个或多个值。

lpop/rpop <key>从左边/右边吐出一个值。值在键在,值光键亡。

rpoplpush <key1><key2>从<key1>列表右边吐出一个值,插到<key2>列表左边。

lrange <key><start><stop>

按照索引下标获得元素(从左到右)

lrange mylist 0 -1 0 左边第一个,-1 右边第一个,(0-1 表示获取所有)

lindex <key><index>按照索引下标获得元素(从左到右)
llen <key>获得列表长度

linsert <key> before <value><newvalue>在<value>的后面插入<newvalue>插入值
lrem <key><n><value>从左边删除 n 个 value(从左到右)
lset<key><index><value>将列表 key 下标为 index 的值替换成 value

3.3.3. 数据结构

List 的数据结构为快速链表 quickList。

首先在列表元素较少的情况下会使用一块连续的内存存储,这个结构是 ziplist,也即是 压缩列表。

它将所有的元素紧挨着一起存储,分配的是一块连续的内存。

当数据量比较多的时候才会改成 quicklist。

因为普通的链表需要的附加指针空间太大,会比较浪费空间。比如这个列表里存的只 是 int 类型的数据,结构上还需要两个额外的指针 prev 和 next。

image-20220519105912372

Redis 将链表和 ziplist 结合起来组成了 quicklist。也就是将多个 ziplist 使用双向指 针串起来使用。这样既满足了快速的插入删除性能,又不会出现太大的空间冗余。

3.4. Redis 集合(Set)

3.4.1. 简介

Redis set 对外提供的功能与 list 类似是一个列表的功能,特殊之处在于 set 是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set 是一个很好的选 择,并且 set 提供了判断某个成员是否在一个 set 集合内的重要接口,这个也是 list 所 不能提供的。

Redis 的 Set 是 string 类型的无序集合。它底层其实是一个 value 为 null 的 hash 表,所 以添加,删除,查找的复杂度都是 O(1)

一个算法,随着数据的增加,执行时间的长短,如果是 O(1),数据增加,查找数据的 时间不变

3.4.2. 常用命令

sadd <key><value1><value2> …
将一个或多个 member 元素加入到集合 key 中,已经存在的 member 元素将被忽略
smembers <key>取出该集合的所有值。sismember <key><value>判断集合<key>是否为含有该<value>值,有 1,没有 0
scard<key>返回该集合的元素个数。
srem <key><value1><value2> … 删除集合中的某个元素。
spop <key>随机从该集合中吐出一个值
srandmember <key><n>随机从该集合中取出 n 个值。不会从集合中删除 。
smove <source><destination>value 把集合中一个值从一个集合移动到另一个集合.
sinter <key1><key2>返回两个集合的交集元素。
sunion <key1><key2>返回两个集合的并集元素。
sdiff <key1><key2>返回两个集合的差集元素(key1 中的,不包含 key2 中的).

3.4.3. 数据结构

Set 数据结构是 dict 字典,字典是用哈希表实现的。

Java 中 HashSet 的内部实现使用的是 HashMap,只不过所有的 value 都指向同一个对 象。Redis 的 set 结构也是一样,它的内部也使用 hash 结构,所有的 value 都指向同一 个内部值。

3.5. Redis 哈希(Hash)

3.5.1. 简介

Redis hash 是一个键值对集合。

Redis hash 是一个 string 类型的 field value 的映射表,hash 特别适合用于存储对 象。

类似 Java 里面的 Map<String,Object>

用户 ID 为查找的 key,存储的 value 用户对象包含姓名,年龄,生日等信息,如果用 普通的 key/value 结构来存储 主要有以下 2 种存储方式:

image-20220519112822347

3.5.2. 常用命令

hset <key><field><value>给<key>集合中的 <field>键赋值<value>

hget <key1><field>从<key1>集合<field>取出 value

hmset <key1><field1><value1><field2><value2>… 批量设置 hash 的值

hexists<key1><field>查看哈希表 key 中,给定域 field 是否存在。

hkeys <key>列出该 hash 集合的所有 field

hvals <key>列出该 hash 集合的所有 value

hincrby <key><field><increment>为哈希表 key 中的域 field 的值加上增量 1 -1

hsetnx <key><field><value>将哈希表 key 中的域 field 的值设置为 value ,当且仅当域field 不存在 .

3.5.3. 数据结构

​ Hash 类型对应的数据结构是两种:ziplist(压缩列表),hashtable(哈希表)。当 field-value 长度较短且个数较少时,使用 ziplist,否则使用 hashtable。

3.6. Redis 有序集合 Zset(sorted set)

3.6.1. 简介

Redis 有序集合 zset 与普通集合 set 非常相似,是一个没有重复元素的字符串集合。

不同之处是有序集合的每个成员都关联了一个评分(score),这个评分(score)被用 来按照从最低分到最高分的方式排序集合中的成员。集合的成员是唯一的,但是评分 可以是重复了

因为元素是有序的, 所以你也可以很快的根据评分(score)或者次序(position)来获 取一个范围的元素。

访问有序集合的中间元素也是非常快的,因此你能够使用有序集合作为一个没有重复成 员的智能列表。

3.6.2. 常用命令

zadd <key><score1><value1><score2><value2>…
将一个或多个 member 元素及其 score 值加入到有序集 key 当中。

zrange <key><start><stop> [WITHSCORES]
返回有序集 key 中,下标在<start><stop>之间的元素
带 WITHSCORES,可以让分数一起和值返回到结果集。

zrangebyscore key minmax [withscores] [limit offset count]
返回有序集 key 中,所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成
员。有序集成员按 score 值递增(从小到大)次序排列。

zrevrangebyscore key maxmin [withscores] [limit offset count]
同上,改为从大到小排列。

zincrby <key><increment><value> 为元素的 score 加上增量

zrem <key><value>删除该集合下,指定值的元素

zcount <key><min><max>统计该集合,分数区间内的元素个数

zrank <key><value>返回该值在集合中的排名,从 0 开始。

案例:如何利用 zset 实现一个文章访问量的排行榜?

image-20220519120030878

3.6.3. 数据结构

​ SortedSet(zset)是 Redis 提供的一个非常特别的数据结构,一方面它等价于 Java 的数据结构 Map,可以给每一个元素 value 赋予一个权重 score,另 一方面它又类似于 TreeSet,内部的元素会按照权重 score 进行排序,可以得到每个元 素的名次,还可以通过 score 的范围来获取元素的列表。

​ zset 底层使用了两个数据结构

(1)hash,hash 的作用就是关联元素 value 和权重 score,保障元素 value 的唯 一性,可以通过元素 value 找到相应的 score 值。 (2)跳跃表,跳跃表的目的在于给元素 value 排序,根据 score 的范围获取元素 列表。

3.6.4. 跳跃表(跳表)

  1. 简介

    有序集合在生活中比较常见,例如根据成绩对学生排名,根据得分对玩家排名 等。对于有序集合的底层实现,可以用数组、平衡树、链表等。数组不便元素的插入、删除;平衡树或红黑树虽然效率高但结构复杂;链表查询需要遍历所有效率低。 Redis 采用的是跳跃表。跳跃表效率堪比红黑树,实现远比红黑树简单。

  2. 对比有序链表和跳跃表,从链表中查询出 51

    1. 有序链表

    image-20220519142657673

    要查找值为 51 的元素,需要从第一个元素开始依次查找、比较才能找到。共 需要 6 次比较。

    1. 跳跃表

      image-20220519142901747

      从第 2 层开始,1 节点比 51 节点小,向后比较。

      21 节点比 51 节点小,继续向后比较,后面就是 NULL 了,所以从 21 节点向下到第 1 层

      在第 1 层,41 节点比 51 节点小,继续向后,61 节点比 51 节点大,所以从 41 向下

      在第 0 层,51 节点为要查找的节点,节点被找到,共查找 4 次。

      从此可以看出跳跃表比有序链表效率要高

Redis 新数据类型

6.1. Bitmaps

6.1.1. 简介

现代计算机用二进制(位) 作为信息的基础单位, 1 个字节等于 8 位, 例如“abc” 字符串是由 3 个字节组成, 但实际在计算机存储时将其用二进制表示, “abc”分别 对应的 ASCII 码分别是 97、 98、 99, 对应的二进制分别是 01100001、 01100010 和 01100011,如下图

image-20220606112136412

合理地使用操作位能够有效地提高内存使用率和开发效率。

Redis 提供了 Bitmaps 这个“数据类型”可以实现对位的操作:

(1) Bitmaps 本身不是一种数据类型, 实际上它就是字符串(key-value) , 但是它可以对字符串的位进行操作。

(2) Bitmaps 单独提供了一套命令, 所以在 Redis 中使用 Bitmaps 和使用字 符串的方法不太相同。 可以把 Bitmaps 想象成一个以位为单位的数组, 数组的每个单元只能存储 0 和 1, 数组的下标在 Bitmaps 中叫做偏移量。

image-20220606113024146

6.1.2. 命令

1、setbit

(1)格式

setbit设置 Bitmaps 中某个偏移量的值(0 或 1)

image-20220606113140212

(2)实例

​ 每个独立用户是否访问过网站存放在 Bitmaps 中, 将访问的用户记做 1, 没有访 问的用户记做 0, 用偏移量作为用户的 id。

设置键的第 offset 个位的值(从 0 算起) , 假设现在有 20 个用户,userid=1, 6, 11, 15, 19 的用户对网站进行了访问, 那么当前 Bitmaps 初始化结果如图

image-20220606150408615

注:

​ 很多应用的用户 id 以一个指定数字(例如 10000) 开头, 直接将用户 id 和 Bitmaps 的偏移量对应势必会造成一定的浪费, 通常的做法是每次做 setbit 操作时将用 户 id 减去这个指定数字。

​ 在第一次初始化 Bitmaps 时, 假如偏移量非常大, 那么整个初始化过程执行会 比较慢, 可能会造成 Redis 的阻塞。

2、getbit

4. Redis 配置文件介绍

自定义目录:/myredis/redis.conf

4.1. ###Units 单位###

配置大小单位,开头定义了一些基本的度量单位,只支持 bytes,不支持 bit

大小写不敏感

image-20220519145825078

4.2. ###INCLUDES 包含###

image-20220519145850701

类似 jsp 中的 include,多实例的情况可以把公用的配置文件提取出来

4.3. ###网络相关配置

4.3.1. bind

默认情况 bind=127.0.0.1 只能接受本机的访问请求

不写的情况下,无限制接受任何 ip 地址的访问

生产环境肯定要写你应用服务器的地址;服务器是需要远程访问的,所以需要将其注 释掉

如果开启了 protected-mode,那么在没有设定 bind ip 且没有设密码的情况下,Redis 只允许接受本机的响应

image-20220519150413396

保存配置,停止服务,重启启动查看进程,不再是本机访问了。

image-20220519150432912

4.3.2. protected-mode

image-20220519150522395

4.3.3. Port

端口号,默认 6379

image-20220519150808995

4.3.4. tcp-backlog

设置 tcp 的 backlog,backlog 其实是一个连接队列,backlog 队列总和=未完成三次握手 队列 + 已经完成三次握手队列。

在高并发环境下你需要一个高 backlog 值来避免慢客户端连接问题。

注意 Linux 内核会将这个值减小到/proc/sys/net/core/somaxconn 的值(128),所以需要 确认增大/proc/sys/net/core/somaxconn 和/proc/sys/net/ipv4/tcp_max_syn_backlog (128)两个值来达到想要的效果

image-20220519150919444

4.3.5. timeout

一个空闲的客户端维持多少秒会关闭,0 表示关闭该功能。即永不关闭

image-20220519151118995

4.3.6. tcp-keepalive

对访问客户端的一种心跳检测,每个 n 秒检测一次。

单位为秒,如果设置为 0,则不会进行 Keepalive 检测,建议设置成 60

image-20220519151406459

4.4. ###GENERAL 通用###

4.4.1. daemonize

是否为后台进程,设置为 yes 守护进程,后台启动

image-20220519152610316

4.4.2. pidfile

存放 pid 文件的位置,每个实例会产生一个不同的 pid 文件

image-20220519152831703

指定日志记录级别,Redis 总共支持四个级别:debug、verbose、notice、warning,默 认为 notice

四个级别根据使用阶段来选择,生产环境选择 notice 或者 warning

4.4.4. logfile

日志文件名称

image-20220519153111868

设定库的数量 默认 16,默认数据库为 0,可以使用 SELECT 命令在连接上指定 数据库 id

image-20220519153150296

4.5. ###SECURITY 安全###

4.5.1. 设置密码

image-20220519153218407

访问密码的查看、设置和取消

在命令中设置密码,只是临时的。重启 redis 服务器,密码就还原了。

永久设置,需要再配置文件中进行设置。

image-20220519153341569

4.6. #### LIMITS 限制

4.6.1. maxclients

➢ 设置 redis 同时可以与多少个客户端进行连接。

➢ 默认情况下为 10000 个客户端。

➢ 如果达到了此限制,redis 则会拒绝新的连接请求,并且向这些连接请求方发出 “max number of clients reached”以作回应。

image-20220519153449809

4.6.2. maxmemory

➢建议必须设置,否则,将内存占满,造成服务器宕机

➢ 设置 redis 可以使用的内存量。一旦到达内存使用上限,redis 将会试图移除内部数 据,移除规则可以通过 maxmemory-policy 来指定。

➢ 如果 redis 无法根据移除规则来移除内存中的数据,或者设置了“不允许移除”, 那么 redis 则会针对那些需要申请内存的指令返回错误信息,比如 SET、LPUSH 等。

➢ 但是对于无内存申请的指令,仍然会正常响应,比如 GET 等。如果你的 redis 是主 redis(说明你的 redis 有从 redis),那么在设置内存使用上限时,需要在系统中留 出一些内存空间给同步队列缓存,只有在你设置的是“不移除”的情况下,才不 用考虑这个因素。

image-20220519153658816

4.6.3. maxmemory-policy

➢volatile-lru:使用 LRU 算法移除 key,只对设置了过期时间的键;(最近最少使 用)

➢ allkeys-lru:在所有集合 key 中,使用 LRU 算法移除 key

➢ volatile-random:在过期集合中移除随机的 key,只对设置了过期时间的键

➢ allkeys-random:在所有集合 key 中,移除随机的 key

➢ volatile-ttl:移除那些 TTL 值最小的 key,即那些最近要过期的 key

➢ noeviction:不进行移除。针对写操作,只是返回错误信息

image-20220519153817536

4.6.4. maxmemory-samples

➢设置样本数量,LRU 算法和最小 TTL 算法都并非是精确的算法,而是估算值,所 以你可以设置样本的大小,redis 默认会检查这么多个 key 并选择其中 LRU 的那 个。

➢ 一般设置 3 到 7 的数字,数值越小样本越不准确,但性能消耗越小。

image-20220519153905228

5. Redis 的发布和订阅

5.1. 什么是发布和订阅

Redis 发布订阅 (pub/sub) 是一种消息通信模式:发送者 (pub) 发送消息,订阅者 (sub) 接收消息。

Redis 客户端可以订阅任意数量的频道。

9. Redis 与 Spring Boot 整合

Spring Boot 整合 Redis 非常简单,只需要按如下步骤整合即可

9.1. 整合步骤

  1. 在 pom.xml 文件中引入 redis 相关依赖

    <!-- redis -->
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    <!-- spring2.X 集成 redis 所需 common-pool2-->
    <dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
    <version>2.6.0</version>
    </dependency>2、 application.properties 配置 redis 配置
    
  2. application.properties 配置 redis 配置

    #Redis 服务器地址
    spring.redis.host=192.168.140.136
    #Redis 服务器连接端口
    spring.redis.port=6379
    #Redis 数据库索引(默认为 0)
    spring.redis.database= 0
    #连接超时时间(毫秒)
    spring.redis.timeout=1800000
    #连接池最大连接数(使用负值表示没有限制)
    spring.redis.lettuce.pool.max-active=20
    #最大阻塞等待时间(负数表示没限制)
    spring.redis.lettuce.pool.max-wait=-1
    #连接池中的最大空闲连接
    spring.redis.lettuce.pool.max-idle=5
    #连接池中的最小空闲连接
    spring.redis.lettuce.pool.min-idle=0
    
    
  3. 添加 redis 配置类

    @EnableCaching
    @Configuration
    public class RedisConfig extends CachingConfigurerSupport {
     @Bean
     public RedisTemplate<String, Object> 
    redisTemplate(RedisConnectionFactory factory) {
     RedisTemplate<String, Object> template = new RedisTemplate<>();
     RedisSerializer<String> redisSerializer = new 
    StringRedisSerializer();
     Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new 
    Jackson2JsonRedisSerializer(Object.class);
     ObjectMapper om = new ObjectMapper();
     om.setVisibility(PropertyAccessor.ALL, 
    JsonAutoDetect.Visibility.ANY);
     om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
     jackson2JsonRedisSerializer.setObjectMapper(om);
     template.setConnectionFactory(factory);
    //key 序列化方式
     template.setKeySerializer(redisSerializer);
    //value 序列化
     template.setValueSerializer(jackson2JsonRedisSerializer);
    //value hashmap 序列化
     template.setHashValueSerializer(jackson2JsonRedisSerializer);
     return template;
     }
     @Bean
     public CacheManager cacheManager(RedisConnectionFactory factory) {
     RedisSerializer<String> redisSerializer = new 
    StringRedisSerializer();
     Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new 
    Jackson2JsonRedisSerializer(Object.class);
    //解决查询缓存转换异常的问题
     ObjectMapper om = new ObjectMapper();
     om.setVisibility(PropertyAccessor.ALL, 
    JsonAutoDetect.Visibility.ANY);
     om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
     jackson2JsonRedisSerializer.setObjectMapper(om);
    // 配置序列化(解决乱码的问题),过期时间 600 秒
     RedisCacheConfiguration config = 
    RedisCacheConfiguration.defaultCacheConfig()
     .entryTtl(Duration.ofSeconds(600))
     .serializeKeysWith(RedisSerializationContext.SerializationPa
    ir.fromSerializer(redisSerializer))
     .serializeValuesWith(RedisSerializationContext.Serialization
    Pair.fromSerializer(jackson2JsonRedisSerializer))
       .disableCachingNullValues();
       RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
     .cacheDefaults(config)
     .build();
     return cacheManager;
     }
    }
    
    
  4. 测试一下

    @RestController
    @RequestMapping("/redisTest")
    public class RedisTestController {
     @Autowired
     private RedisTemplate redisTemplate;
     @GetMapping
     public String testRedis() {
     //设置值到 redis
     redisTemplate.opsForValue().set("name","lucy");
     //从 redis 获取值
     String name = (String)redisTemplate.opsForValue().get("name");
     return name;
     }
    }
    
    

eysWith(RedisSerializationContext.SerializationPa
ir.fromSerializer(redisSerializer))
.serializeValuesWith(RedisSerializationContext.Serialization
Pair.fromSerializer(jackson2JsonRedisSerializer))
.disableCachingNullValues();
RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build();
return cacheManager;
}
}


4. 测试一下

```java
@RestController
@RequestMapping("/redisTest")
public class RedisTestController {
 @Autowired
 private RedisTemplate redisTemplate;
 @GetMapping
 public String testRedis() {
 //设置值到 redis
 redisTemplate.opsForValue().set("name","lucy");
 //从 redis 获取值
 String name = (String)redisTemplate.opsForValue().get("name");
 return name;
 }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值