redis学习

2023-09-20 21:23:07

Redis

​ redis是一个开源的使用ansi c语言编写、支持网络、可基于内存亦可持久化的日志型、key-value数据库,并提供多种语言的api。从2010年3月15日起,redis的开发工作由vmware主持.

和MySQL一样都是数据仓库,用于存放数据的仓库,存储和管理

磁盘查询数据时顺序IO随机IO

mysqI底层使用什么方式进行存储的?

文件形式存储数据结构用于保存数据B+Tree

高并发 顺序性 树的节点少方便查询MySQL 查询的优化,优化的是查询速度

学习使用redis的目的:满足高并发的应用场景和为了能够更加方便的存储和使用web2.0时代的爆炸性数据

关系型数据库

​ 关系型数据库,是指采用了关系模型来组织数据的数据库,其以行和列的形式存储数据,以便于用户理解,关系型数据库这一系列的行和列被称为表,一组表组成了数据库。用户通过查询来检索数据库中的数据,而查询是一个用于限定数据库中某些区域的执行代码。关系模型可以简单理解为二维表格模型,而一个关系型数据库就是由二维表及其之间的关系组成的一个数据组织.

关系模型中常用的概念:

  • 关系:可以理解为一张二维表,每个关系都具有一个关系名,就是通常说的表名
  • 元组:可以理解为二维表中的一行,在数据库中经常被称为记录
  • 属性:可以理解为二维表中的一列,在数据库中经常被称为字段
  • 域:属性的取值范围,也就是数据库中某一列的取值限制
  • 关键字:一组可以唯一标识元组的属性,数据库中常称为主键,由一个或多个列组成
  • 关系模式:指对关系的描述。其格式为:关系名(属性1,属性2, … … ,属性N),在数据库中成为表结构

关系型数据库的优点:

  • 容易理解:二维表结构是非常贴近逻辑世界的一个概念,关系模型相对网状、层次等其他模型来说更容易理解

  • 使用方便:通用的SQL语言使得操作关系型数据库非常方便

  • 易于维护:丰富的完整性(实体完整性、参照完整性和用户定义的完整性)大大减低了数据冗余和数据不一致的概率

关系型数据库瓶颈

  • 高并发读写需求

网站的用户并发性非常高,往往达到每秒上万次读写请求,对于传统关系型数据库来说,硬盘I/O是一个很大的瓶颈

  • 海量数据的高效率读写

网站每天产生的数据量是巨大的,对于关系型数据库来说,在一张包含海量数据的表中查询,效率是非常低的

  • 高扩展性和可用性

​ 在基于web的结构当中,数据库是最难进行横向扩展的,当一个应用系统的用户量和访问量与日俱增的时候,数据库却没有办法像web server和app server那样简单的通过添加更多的硬件和服务节点来扩展性能和负载能力。对于很多需要提供24小时不间断服务的网站来说,对数据库系统进行升级和扩展是非常痛苦的事情,往往需要停机维护和数据迁移。

对网站来说,关系型数据库的很多特性不再需要了:

  • 事务一致性

关系型数据库在对事物一致性的维护中有很大的开销,而现在很多web2.0系统对事物的读写一致性都不高

  • 读写实时性

对关系数据库来说,插入一条数据之后立刻查询,是肯定可以读出这条数据的,但是对于很多web应用来说,并不要求这么高的实时性,比如发一条消息之后,过几秒乃至十几秒之后才看到这条动态是完全可以接受的

  • 复杂SQL,特别是多表关联查询

任何大数据量的web系统,都非常忌讳多个大表的关联查询,以及复杂的数据分析类型的复杂SQL报表查询,特别是SNS类型的网站,从需求以及产品阶级角度,就避免了这种情况的产生。往往更多的只是单表的主键查询,以及单表的简单条件分页查询,SQL的功能极大的弱化了

​ 在关系型数据库中,导致性能欠佳的最主要原因是多表的关联查询,以及复杂的数据分析类型的复杂SQL报表查询。为了保证数据库的ACID特性,我们 必须尽量按照其要求的范式进行设计,关系型数据库中的表都是存储一个格式化的数据结构。每个元组字段的组成都是一样,即使不是每个元组都需要所有的字段, 但数据库会为每个元组分配所有的字段,这样的结构可以便于标语表之间进行链接等操作,但从另一个角度来说它也是关系型数据库性能瓶颈的一个因素。

非关系型数据库

​ NoSQL一词首先是Carlo Strozzi在1998年提出来的,指的是他开发的一个没有SQL功能,轻量级的,开源的关系型数据库。这个定义跟我们现在对NoSQL的定义有很大的 区别,它确确实实字如其名,指的就是“没有SQL”的数据库。但是NoSQL的发展慢慢偏离了初衷,我们要的不是“no sql”,而是“no relational”,也就是我们现在常说的非关系型数据库了。

​ 2009年初,Johan Oskarsson举办了一场关于开源分布式数据库的讨论,Eric Evans在这次讨论中再次提出了NoSQL一词,用于指代那些非关系型的,分布式的,且一般不保证遵循ACID原则的数据存储系统。Eric Evans使用NoSQL这个词,并不是因为字面上的“没有SQL”的意思,他只是觉得很多经典的关系型数据库名字都叫“**SQL”,所以为了表示跟这些关系型数据库在定位上的截然不同,就是用了“NoSQL“一词。

注:数据库事务必须具备ACID特性,ACID是Atomic原子性,Consistency一致性,Isolation隔离性,Durability持久性。

​ 非关系型数据库提出另一种理念,例如,以键值对存储,且结构不固定,每一个元组可以有不一样的字段,每个元组可以根据需要增加一些自己的键值对,这 样就不会局限于固定的结构,可以减少一些时间和空间的开销。使用这种方式,用户可以根据需要去添加自己需要的字段,这样,为了获取用户的不同信息,不需要 像关系型数据库中,要对多表进行关联查询。仅需要根据id取出相应的value就可以完成查询。但非关系型数据库由于很少的约束,他也不能够提供像SQL 所提供的where这种对于字段属性值情况的查询。并且难以体现设计的完整性。他只适合存储一些较为简单的数据,对于需要进行较复杂查询的数据,SQL数 据库显的更为合适。

关系型数据库 V.S. 非关系型数据库

​ 关系型数据库的最大特点就是事务的一致性:传统的关系型数据库读写操作都是事务的,具有ACID的特点,这个特性使得关系型数据库可以用于几乎所有对一致性有要求的系统中,如典型的银行系统。

但是,在网页应用中,尤其是SNS应用中,一致性却不是显得那么重要,用户A看到的内容和用户B看到同一用户C内容更新不一致是可以容忍的,或者 说,两个人看到同一好友的数据更新的时间差那么几秒是可以容忍的,因此,关系型数据库的最大特点在这里已经无用武之地,起码不是那么重要了。

相反地,关系型数据库为了维护一致性所付出的巨大代价就是其读写性能比较差,而像微博、facebook这类SNS的应用,对并发读写能力要求极 高,关系型数据库已经无法应付(在读方面,传统上为了克服关系型数据库缺陷,提高性能,都是增加一级memcache来静态化网页,而在SNS中,变化太 快,memchache已经无能为力了),因此,必须用新的一种数据结构存储来代替关系数据库。

关系数据库的另一个特点就是其具有固定的表结构,因此,其扩展性极差,而在SNS中,系统的升级,功能的增加,往往意味着数据结构巨大变动,这一点关系型数据库也难以应付,需要新的结构化数据存储。

于是,非关系型数据库应运而生,由于不可能用一种数据结构化存储应付所有的新的需求,因此,非关系型数据库严格上不是一种数据库,应该是一种数据结构化存储方法的集合。

NoSQL相关产品

非关系数据库产品与分类

K-V

键值(key-value)存储数据库

相关产品: tokyo cabinet/tyrant、redis、voldemort、berkeley db

典型应用: 内容缓存,主要用于处理大量数据的高访问负载。

数据模型: 一系列键值对

优势: 快速查询

劣势: 存储的数据缺少结构化

列存储数据库

相关产品:cassandra, hbase, riak

典型应用:分布式的文件系统

数据模型:以列簇式存储,将同一列数据存在一起

优势:查找速度快,可扩展性强,更容易进行分布式扩展

劣势:功能相对局限

文档型数据库

相关产品:couchdb、mongodb json存储

典型应用:web应用(与key-value类似,value是结构化的)

数据模型: 一系列键值对

优势:数据结构要求不严格

劣势:查询性能不高,而且缺乏统一的查询语法

图形(graph)数据库

相关数据库:neo4j、infogrid、infinite graph

典型应用:社交网络

数据模型:图结构

优势:利用图结构相关算法。

劣势:需要对整个图做计算才能得出结果,不容易做分布式的集群方案。

Redis

​ 2008年,意大利的一家创业公司merzia推出了一款基于mysql的网站实时统计系统lloogg,然而没过多久该公司的创始人 salvatore sanfilippo便 对mysql的性能感到失望,于是他决定亲自为lloogg量身定做一个数据库,并于2009年开发完成,这个数据库就是redis。 不过salvatore sanfilippo并不满足只将redis用于lloogg这一款产品,而是希望更多的人使用它,于是在同一年salvatore sanfilippo将redis开源发布,并开始和redis的另一名主要的代码贡献者pieter noordhuis一起继续着redis的开发,直到今天。

​ salvatore sanfilippo自己也没有想到,短短的几年时间,redis就拥有了庞大的用户群体。hacker news在2012年发布了一份数据库的使用情况调查,结果显示有近12%的公司在使用redis。国内如新浪微博、街旁网、知乎网,国外如github、stack overflow、flickr等都是redis的用户。

​ vmware公司从2010年开始赞助redis的开发, salvatore sanfilippo和pieter noordhuis也分别在3月和5月加入vmware,全职开发redis。

Redis中的数据类型

​ redis是用c语言开发的一个开源的高性能键值对(key-value)数据库。它通过提供多种键值数据类型来适应不同场景下的存储需求,目前为止redis支持的常用键值数据类型如下:

字符串类型

散列类型

列表类型

集合类型

有序集合类型

启动redis服务

启动时指定配置文件,建议使用这种方式,使用vim修改配置文件redis.conf ,将daemonize no 改成 yes ,然后保存退出.

启动redis服务

redis-server ./redis.conf 
#停止redis服务
redis-cli -h 192.168.25.126 -p 6379 shutdown 

进入客户端:

 redis-cli -h 192.168.25.126 -p 6379 --raw
 
 #带上-c是表示启动的是redis集群
 
 redis-cli -c -h 192.168.25.116 -p 6381

查看Redis进程

ps -aux | grep redis

sh脚本启动redis集群

./redis-cluster-start.sh

清空redis:

flushdb

Redis操作

String类型

​ string 是 redis 最基本的类型,一个 key 对应一个 value,string 类型是二进制安全的。意思是 redis 的 string 可以包含任何数据。比如jpg图片或者序列化的对象.string 类型是 redis 最基本的数据类型,string 类型的值最大能存储 512mb。

set key value […]

set key value

mset key value key2 value2…

get key

exists key

del key 删除用于任何类型

incr key 设置数值递增1 (key得是数值类型)

decr key 递减1

setnx 检查一个key是否存在 当存在时不做任何操作 ,如果不存在才会创建

实现上setnx在执行检查时是属于原子操作,不会被破坏 分布式锁中需要使用setnx机制来进行加锁操作

锁——公共资源任何进程都能对其进行操作 公平

set key value ex[秒]/px[毫秒] 在多少秒/毫秒内key有效

ttl key 查看数据过期时间

过期key删除策略,惰性删除机制 主动删除有损cpu计算

不是内存淘汰策略——当运行redis的节点内存不足时redis进行的内存优化策略

Redis 字符串命令

下表列出了常用的 redis 字符串命令:

序号命令及描述
1[set key value] 设置指定 key 的值。
2[get key] 获取指定 key 的值。
3[getrange key start end] 返回 key 中字符串值的子字符
4[GETSET key value] 将给定 key 的值设为 value ,并返回 key 的旧值(old value)。
5[GETBIT key offset] 对 key 所储存的字符串值,获取指定偏移量上的位(bit)。
6[MGET key1 [key2…]] 获取所有(一个或多个)给定 key 的值。
7[SETBIT key offset value] 对 key 所储存的字符串值,设置或清除指定偏移量上的位(bit)。
8[SETEX key seconds value] 将值 value 关联到 key ,并将 key 的过期时间设为 seconds (以秒为单位)。
9[SETNX key value] 只有在 key 不存在时设置 key 的值。
10[SETRANGE key offset value] 用 value 参数覆写给定 key 所储存的字符串值,从偏移量 offset 开始。
11[STRLEN key] 返回 key 所储存的字符串值的长度。
12[MSET key value [key value …]] 同时设置一个或多个 key-value 对。
13[MSETNX key value [key value …]] 同时设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在。
14[PSETEX key milliseconds value] 这个命令和 SETEX 命令相似,但它以毫秒为单位设置 key 的生存时间,而不是像 SETEX 命令那样,以秒为单位。
15[INCR key] 将 key 中储存的数字值增一。
16[INCRBY key increment] 将 key 所储存的值加上给定的增量值(increment) 。
17[INCRBYFLOAT key increment] 将 key 所储存的值加上给定的浮点增量值(increment) 。
18[DECR key] 将 key 中储存的数字值减一。
19[DECRBY key decrement] key 所储存的值减去给定的减量值(decrement) 。
20[APPEND key value] 如果 key 已经存在并且是一个字符串, APPEND 命令将指定的 value 追加到该 key 原来值(value)的末尾。

Hash常用操作命令

​ Redis 列表是简单的字符串列表。列表最多可存储 2的32次方- 1 元素 (4294967295, 每个列表可存储40多亿),将哈希表 key 中的域 field 的值设为 value 如果 key 不存在,一个新的哈希表被创建并进行hset操作,如果域 field 已经存在于哈希表中,旧值将被覆盖。
在这里插入图片描述

hset key field value

hget key field

设置多个值:

hmset key field value [field value] hmset user 5 {id:1,name:zs,age:12} 6 {id:1,name:zs,age:12}

hmget key field [field] hmget user 5 6

取所有 字段

hgetall key

通过key删除所有数据 – 通用:

del student

删除hash某个字段

hdel key field 通过值的key删除指定的数据

hincrby key field 增加的数值

hexists key field 是否存在字段

hsetnx key field 如果不存在则添加,存在不做任何操作

只获取字段或值:

hkeys key 获取所有的key

hvals key 获取所有的值

hlen key 读取当前hash表(map集合)中数据的个数

只能对key设置超时时间

Redis hash 命令

下表列出了 redis hash 基本的相关命令:

序号命令及描述
1[hdel key field1 field2] 删除一个或多个哈希表字段
2[HEXISTS key field] 查看哈希表 key 中,指定的字段是否存在。
3[HGET key field] 获取存储在哈希表中指定字段的值。
4[HGETALL key] 获取在哈希表中指定 key 的所有字段和值
5[HINCRBY key field increment] 为哈希表 key 中的指定字段的整数值加上增量 increment 。
6[HINCRBYFLOAT key field increment] 为哈希表 key 中的指定字段的浮点数值加上增量 increment 。
7[HKEYS key] 获取哈希表中的所有字段
8[HLEN key] 获取哈希表中字段的数量
9[HMGET key field1 [field2]] 获取所有给定字段的值
10[HMSET key field1 value1 [field2 value2 ]] 同时将多个 field-value (域-值)对设置到哈希表 key 中。
11[HSET key field value] 将哈希表 key 中的字段 field 的值设为 value 。
12[HSETNX key field value] 只有在字段 field 不存在时,设置哈希表字段的值。
13[HVALS key] 获取哈希表中所有值。
14[HSCAN key cursor [MATCH pattern] [COUNT count]] 迭代哈希表中的键值对。

List常用操作命令

​ 列表类型(list)可以存储一个有序的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边),常用的操作是向列表两端添加元素,或者获得列表的某一个片段.列表类型内部是使用双向链表(double linked list)实现的,所以向列表两端添加元素的时间复杂度为0(1),获取越接近两端的元素速度就越快。这意味着即使是一个有几千万个元素的列表,获取头部或尾部的10条记录也是极快的。

lpush key value

rpush key value

lrange key start stop 开始位置 结束位置 0 -1

lpop key 弹出一个元素 (从集合中删除)

rpop key

llen key

lrem 删除元素 count 删除的个数 ,正个数,从左侧寻找删除,负个数右侧寻找删除,全删除0

linsert key before|after 原始值位置 新的值

#在指定的一个位置前面插入值(不是索引)
192.168.25.116:6381> linsert user before 345 12345
#在指定的一个位置后面插入值(不是索引)
192.168.25.116:6381> linsert user after 345 12345

两个列表值交换 需要两个列表, 第一个列表中的最后一个值插入到第二个列表中的第一位
rpoplpush r pop 1 push (右弹出左推进) 如果1ist1和1ist2为同一个,最后一个值置顶
rpoplpush list1[第一个列表] list2[第二个列表]

192.168.25.116:6381> rpoplpush  stu teacher
#置顶数据
192.168.25.116:6381> rpoplpush  teacherteacher

Set无序集合常用命令

set 是 string 类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据,redis 中集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 o(1)。集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)

使用俩个集合中差集时需要俩个都是set无序集合

sadd key value 添加元素

smembers key 查询元素

scard key 获取成员数

sdiff key1 key2 集合差异

sinter key1 key2 集合交集 a,b,c b,z,y

sunion key1 key2 集合并集

spop key 随机一个元素

srem key member 移除集合成员

Redis (Set)集合命令

下表列出了 Redis 集合基本命令:

序号命令及描述
1[sadd key member1 member2] 向集合添加一个或多个成员
2[scard key] 获取集合的成员数
3[sdiff key1 key2] 返回第一个集合与其他集合之间的差异。
4[SDIFFSTORE destination key1 key2] 返回给定所有集合的差集并存储在 destination 中
5[SINTER key1 key2] 返回给定所有集合的交集
6[SINTERSTORE destination key1 key2] 返回给定所有集合的交集并存储在 destination 中
7[sismember key member] 判断 member 元素是否是集合 key 的成员
8SMEMBERS key []返回集合中的所有成员
9SMOVE source destination member 将 member 元素从 source 集合移动到 destination 集合
10SPOP key 移除并返回集合中的一个随机元素
11[srandmember key count] 返回集合中一个或多个随机数
12[srem key member1 member2] 移除集合中一个或多个成员
13[sunion key1 key2] 返回所有给定集合的并集
14[SUNIONSTORE destination key1 key2] 所有给定集合的并集存储在 destination 集合中
15[SSCAN key cursor MATCH pattern] [COUNT count] 迭代集合中的元素

Zset类型学习 :

有序不重复集合ZSet也就是SortedSet(可排序集合),其中每一个元素都需要指定一个score值和member值:
可以根据score值排序后
member必须唯一
score
可以根据member查询分数

zrange emps 0 -1(查询 - 默认升序)

+inf 正无穷

-inf 负无穷

序号命令及描述
1[zadd key score1 member1 [score2 member2 …]] 向有序集合添加一个或多个成员,或者更新已存在成员的分数
2[zcard key] 获取有序集合的成员数
3[zcount key min max] 计算在有序集合中指定区间分数的成员数
4[zincrby key increment member] 有序集合中对指定成员的分数加上增量 increment
5[ZINTERSTORE destination numkeys key [key …]] 计算给定的一个或多个有序集的交集并将结果集存储在新的有序集合 destination 中
6[ZLEXCOUNT key min max] 在有序集合中计算指定字典区间内成员数量
7[ZRANGE key start stop [WITHSCORES]] 通过索引区间返回有序集合指定区间内的成员
8[ZRANGEBYLEX key min max [LIMIT offset count]] 通过字典区间返回有序集合的成员
9[ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT]] 通过分数返回有序集合指定区间内的成员
10[ZRANK key member] 返回有序集合中指定成员的索引
11[ZREM key member [member …]] 移除有序集合中的一个或多个成员
12[ZREMRANGEBYLEX key min max] 移除有序集合中给定的字典区间的所有成员
13[ZREMRANGEBYRANK key start stop] 移除有序集合中给定的排名区间的所有成员
14[ZREMRANGEBYSCORE key min max] 移除有序集合中给定的分数区间的所有成员
15[ZREVRANGE key start stop [WITHSCORES]] 返回有序集中指定区间内的成员,通过索引,分数从高到低
16[ZREVRANGEBYSCORE key max min [WITHSCORES]] 返回有序集中指定分数区间内的成员,分数从高到低排序
17[ZREVRANK key member] 返回有序集合中指定成员的排名,有序集成员按分数值递减(从大到小)排序
18[zscore key member] 返回有序集中,成员的分数值
19[ZUNIONSTORE destination numkeys key [key …]] 计算给定的一个或多个有序集的并集,并存储在新的 key 中
20[ZSCAN key cursor [MATCH pattern] [COUNT count]] 迭代有序集合中的元素(包括元素成员和元素分值)

redis数据持久化

​ redis是一个内存数据库,数据保存在内存中,但是我们都知道内存的数据变化是很快的,也容易发生丢失。幸好Redis还为我们提供了持久化的机制,分别是RDB(Redis DataBase)和AOF(Append Only File)。

将数据从内存中持久(保存中的过程持久化
单机游戏保存到电脑的磁盘中,当你下次在登录时从磁盘中读取进度数据加载到游戏中
数据保存到可掉电的设备中加入固化
数据有可能会丢失内存中运行磁盘
序列化 反序列化
redis在运行时数据都是通过内存中进行存放运行redis的机器宕机了那么内存数据不再了持久化机制
持久化机制:什么时候放以什么方式存放
数据快照
策略机制:
自动保存快照
设置阈值
在多少时间内有多少次写操作时进行触发保存,当正常退出redis服务时会触发一次写磁盘操作不是宕机
手动保存快照
aof日志文件

redis默认是使用rdb数据快照方式进行日志记录,aof需要手动设置开启才能使用.
set usemame zhangsan文件
rdb aof日志文件恢复速度上快照要比aof文件恢复快,在数据安全上aof要比rdb安全一些

数据持久化实现方式

rdb的创建位置是在redis-server执行位置上创建的及读取的

RDB数据快照

​ RDB持久化是将当前进程中的数据生成快照保存到硬盘(因此也称作快照持久化),保存的文件后缀是rdb;当Redis重新启动时,可以读取快照文件恢复数据

rdb触发条件
1.手动触发

save命令和bgsave命令都可以生成RDB文件。

save命令会阻塞Redis服务器进程,直到RDB文件创建完毕为止,在Redis服务器阻塞期间,服务器不能处理任何命令请求。

bgsave命令会创建一个子进程,由子进程来负责创建RDB文件,父进程(即Redis主进程)则继续处理请求。

bgsave命令执行过程中,只有fork子进程时会阻塞服务器,而对于save命令,整个过程都会阻塞服务器,因此save已基本被废弃,线上环境要杜绝save的使用,在自动触发RDB持久化时,Redis也会选择bgsave而不是save来进行持久化
在这里插入图片描述

2.自动触发

自动触发最常见的情况是在配置文件中通过save m n,指定当m秒内发生n次变化时,会触发bgsave。

例如,查看redis的默认配置文件(Linux下为redis根目录下的redis.conf),可以看到如下配置信息
在这里插入图片描述
​ 其中save 900 1的含义是:当时间到900秒时,如果redis数据发生了至少1次变化,则执行bgsave;save 300 10和save 60 10000同理。当三个save条件满足任意一个时,都会引起bgsave的调用

rdb文件存储位置

RDB文件的存储路径既可以在启动前配置,也可以通过命令动态设定。

配置:dir配置指定目录,dbfilename指定文件名。默认是Redis根目录下的dump.rdb文件
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

AOF文件追加

​ 快照功能(rdb)并不是非常耐久(durable): 如果 redis 因为某些原因而造成故障停机, 那么服务器将丢失最近写入、且仍未保存到快照中的那些数据。 从 1.1 版本开始, redis 增加了一种完全耐久的持久化方式:
aof 持久化。
你可以在配置文件中打开aof方式

​ AOF 即 append only file,當 redis 採用這這種數據持久化策略的時候,每當 redis 服務器收到一條更新命令時,操作結束之後會將這條命令添加到 aof 內存緩衝區,特定的時間下刷新緩衝區到磁盤文件中,也就是我們的 aof 文件

每条指令的记录 set username zhangsan -->底层协议指令

appendonly yes

在这里插入图片描述
​ 当打开aof后, 每当 redis 执行一个改变数据集的命令时(比如 set), 这个命令就会被追加到 aof 文件的末尾。这样的话, 当 redis 重新启时, 程序就可以通过重新执行 aof 文件中的命令来达到重建数据集的目的

当每次在redis中发生写的命令时就会触发aof文件的追加操作
在这里插入图片描述
在这里插入图片描述

aof持久化三种策略

always

每次有新命令追加到 aof 文件时就执行一次 fsync :非常慢,也非常安全。
在这里插入图片描述

everysec

每秒 fsync 一次:足够快(和使用 rdb 持久化差不多),并且在故障时只会丢失 1 秒钟的数据。
推荐(并且也是默认)的措施为每秒 fsync 一次, 这种 fsync 策略可以兼顾速度和安全性。
在这里插入图片描述

no

从不 fsync :将数据交给操作系统来处理,由操作系统来决定什么时候同步数据。更快,也更不安全的选择。
在这里插入图片描述

always、everysecno对比
命令优点缺点
always不丢失数据io开销大,一般sata磁盘只有几百tps
everysec每秒进行与fsync,最多丢失1秒数据可能丢失1秒数据
no不用管不可控

AOF重写

将aof日志文件进行优化

​ 隨著 redis 服務器運行時間的持續,生成的 aof 文件只會越來越大,redis 提供 AOF 重寫策略幫助優化和壓縮 aof 文件

aof文件重写的作用

  • 减少磁盘占用量
  • 加速数据恢复

redis的bgrewriteaof 命令用于异步执行一个 aof(appendonly file)文件重写操作。重写会创建一个当前aof文件的体积优化版本。
即使 bgrewriteaof 执行失败,也不会有任何数据丢失,因为旧的aof文件在 bgrewriteaof 成功之前不会被修改。
aof 重写由 redis 自行触发,bgrewriteaof 仅仅用于手动触发重写操作。

  • aof重写配置
配置名含义
auto-aof-rewrite-min-size触发aof文件执行重写的最小尺寸
auto-aof-rewrite-percentage触发aof文件执行重写的增长率
统计名含义
aof_current_sizeaof文件当前尺寸(字节)
aof_base_sizeaof文件上次启动和重写时的尺寸(字节)

aof重写自动触发机制,需要同时满足下面两个条件:

  • aof_current_size > auto-aof-rewrite-min-size
  • (aof_current_size - aof_base_size) * 100 / aof_base_size > auto-aof-rewrite-percentage
  • 假设 redis 的配置项为:
  • auto-aof-rewrite-min-size 64mb
  • auto-aof-rewrite-percentage 100
  • 当aof文件的体积大于64mb,并且aof文件的体积比上一次重写之久的体积大了至少一倍(100%)时,redis将执行 bgrewriteaof 命令进行重写。

rdb 和 aof 对比

-rdbaof
启动优先级
体积
恢复速度
数据安全性丢数据根据策略决定

通过程序整合使用Redis

在这里插入图片描述
​ Spring Data Redis(SDR)框架通过Spring出色的基础架构支持消除了与存储库交互所需的冗余任务和样板代码,从而简化了编写使用Redis键值存储库的Spring应用程序的过程

通过maven构建ssm应用架构及引入redis依赖

pom:

<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<spring.version>4.1.1.RELEASE</spring.version>
	</properties>
  
  <dependencies>
  	<!-- spring mvc -->
  	<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>${spring.version}</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring.version}</version>
		</dependency>
  
  <!-- servlet -->
  		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>3.1.0</version>
			<scope>provided</scope>
		</dependency>

		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>jsp-api</artifactId>
			<version>2.2</version>
			<scope>provided</scope>
		</dependency>

		<dependency>
			<groupId>jstl</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
			<scope>compile</scope>
		</dependency>
  
		<dependency>
		    <groupId>com.fasterxml.jackson.core</groupId>
		    <artifactId>jackson-core</artifactId>
		    <version>2.2.3</version>
		</dependency>
		
		<dependency>
			 <groupId>com.fasterxml.jackson.core</groupId>
			  <artifactId>jackson-annotations</artifactId>
			  <version>2.2.3</version>
		</dependency>
		
		<dependency>
			  <groupId>com.fasterxml.jackson.core</groupId>
			  <artifactId>jackson-databind</artifactId>
			  <version>2.2.3</version>
		</dependency>

		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.11</version>
			<scope>test</scope>
		</dependency>

		<!-- spring begin -->

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jdbc</artifactId>
			<version>${spring.version}</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context-support</artifactId>
			<version>${spring.version}</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-aop</artifactId>
			<version>${spring.version}</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
			<version>${spring.version}</version>
		</dependency>

		<dependency>
			<groupId>aspectj</groupId>
			<artifactId>aspectjweaver</artifactId>
			<version>1.5.4</version>
		</dependency>


		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-lang3</artifactId>
			<version>3.4</version>
		</dependency>

		<dependency>
			<groupId>commons-io</groupId>
			<artifactId>commons-io</artifactId>
			<version>2.4</version>
		</dependency>

		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-collections4</artifactId>
			<version>4.0</version>
		</dependency>

		<dependency>
			<groupId>commons-logging</groupId>
			<artifactId>commons-logging</artifactId>
			<version>1.1.3</version>
		</dependency>

		<dependency>
			<groupId>commons-codec</groupId>
			<artifactId>commons-codec</artifactId>
			<version>1.8</version>
		</dependency>

		<dependency>
			<groupId>commons-beanutils</groupId>
			<artifactId>commons-beanutils</artifactId>
			<version>1.8.3</version>
		</dependency>

		<dependency>
			<groupId>commons-chain</groupId>
			<artifactId>commons-chain</artifactId>
			<version>1.2</version>
		</dependency>

		<dependency>
			<groupId>commons-fileupload</groupId>
			<artifactId>commons-fileupload</artifactId>
			<version>1.3.1</version>
		</dependency>

		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-math3</artifactId>
			<version>3.5</version>
		</dependency>

		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-digester3</artifactId>
			<version>3.2</version>
		</dependency>

		<dependency>
			<groupId>commons-net</groupId>
			<artifactId>commons-net</artifactId>
			<version>3.3</version>
		</dependency>

		<dependency>
			<groupId>commons-dbutils</groupId>
			<artifactId>commons-dbutils</artifactId>
			<version>1.5</version>
		</dependency>

		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-email</artifactId>
			<version>1.3.3</version>
		</dependency>
		<!-- dbcp -->
		<!-- <dependency> <groupId>commons-dbcp</groupId> <artifactId>commons-dbcp</artifactId> 
			<version>1.4</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> 
			<artifactId>commons-pool2</artifactId> <version>2.2</version> </dependency> -->

		<!-- c3p0 -->

		<dependency>
			<groupId>com.mchange</groupId>
			<artifactId>c3p0</artifactId>
			<version>0.9.5-pre8</version>
		</dependency>

		<dependency>
			<groupId>com.mchange</groupId>
			<artifactId>mchange-commons-java</artifactId>
			<version>0.2.12</version>
		</dependency>

		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.16</version>
		</dependency>

		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>1.7.5</version>
		</dependency>

		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>1.7.20</version>
		</dependency>

		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis-spring</artifactId>
			<version>1.3.1</version>
		</dependency>

		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis</artifactId>
			<version>3.2.8</version>
		</dependency>

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.30</version>
		</dependency>

		<dependency>
			<groupId>org.mybatis.generator</groupId>
			<artifactId>mybatis-generator-core</artifactId>
			<version>1.3.2</version>
		</dependency>

		<dependency>
			<groupId>net.sf.ehcache</groupId>
			<artifactId>ehcache</artifactId>
			<version>2.10.3</version>
		</dependency>


		<!-- redis -->
		<dependency>
			<groupId>org.springframework.data</groupId>
			<artifactId>spring-data-redis</artifactId>
			<version>1.6.1.RELEASE</version>
		</dependency>
		
		<dependency>
			<groupId>redis.clients</groupId>
			<artifactId>jedis</artifactId>
			<version>2.7.3</version>
		</dependency>
		
		
  </dependencies>
  	<build>
  	<finalName>redis</finalName> 
		<pluginManagement>
			<plugins>
				<plugin>
					<groupId>org.mybatis.generator</groupId>
					<artifactId>mybatis-generator-maven-plugin</artifactId>
					<version>1.3.2</version>
					<dependencies>
						<dependency>
							<groupId>mysql</groupId>
							<artifactId>mysql-connector-java</artifactId>
							<version>5.1.35</version>
						</dependency>
					</dependencies>
					<configuration>
						<!--配置文件的路径 -->
						<configurationFile>${basedir}/src/main/resources/generatorConfig.xml</configurationFile>
						<overwrite>true</overwrite>
					</configuration>
				</plugin>
			<plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.5.1</version>
                <configuration>
                    <source>${java-version}</source>
                    <target>${java-version}</target>
                    <compilerArgument>-Xlint:all</compilerArgument>
                    <showWarnings>true</showWarnings>
                    <showDeprecation>true</showDeprecation>
                </configuration>
            </plugin>
				<plugin>
			        <groupId>org.apache.maven.plugins</groupId>    
			        <artifactId>maven-war-plugin</artifactId>    
			        <version>2.1.1</version>    
			        <configuration>    
              			<webXml>src/main/webapp\WEB-INF\web.xml</webXml>            
        				<warSourceDirectory>src/main/webapp</warSourceDirectory>  
        			</configuration>    
    			</plugin>    
			</plugins>
		</pluginManagement>
<!-- 部署时需要携带配置文件 -->
		<resources>
			<resource>
				<directory>src/main/resources</directory>
				<includes>
					<include>**/*.properties</include>
					<include>**/*.xml</include>
					<!-- c -->
					<include>**/*.tld</include>
				</includes>
				<filtering>false</filtering>
			</resource>
			<resource>
				<directory>src/main/java</directory>
				<includes>
					<include>**/*.properties</include>
					<include>**/*.xml</include>
					<include>**/*.tld</include>
				</includes>
				<filtering>false</filtering>
			</resource>
		</resources>
		</build>

redis.properties配置文件

redis中需要将bind ip 修改为局域网ip 127.0.0.1 ,将redis中的默认受保护模式关闭

#redis\u4E2D\u5FC3
#\u7ED1\u5B9A\u7684\u4E3B\u673A\u5730\u5740
redis.host=
#\u6307\u5B9ARedis\u76D1\u542C\u7AEF\u53E3\uFF0C\u9ED8\u8BA4\u7AEF\u53E3\u4E3A6379
redis.port=
#\u6388\u6743\u5BC6\u7801\uFF08\u53EF\u4EE5\u4E0D\u4F7F\u7528\uFF09
#redis.password=bjtu
#\u6700\u5927\u7A7A\u95F2\u6570\uFF1A\u7A7A\u95F2\u94FE\u63A5\u6570\u5927\u4E8EmaxIdle\u65F6\uFF0C\u5C06\u8FDB\u884C\u56DE\u6536
redis.maxIdle=100
#\u6700\u5927\u8FDE\u63A5\u6570\uFF1A\u80FD\u591F\u540C\u65F6\u5EFA\u7ACB\u7684\u201C\u6700\u5927\u94FE\u63A5\u4E2A\u6570\u201D
redis.maxTotal=200
#\u6700\u5927\u7B49\u5F85\u65F6\u95F4\uFF1A\u5355\u4F4Dms
redis.maxWait=1000
#\u4F7F\u7528\u8FDE\u63A5\u65F6\uFF0C\u68C0\u6D4B\u8FDE\u63A5\u662F\u5426\u6210\u529F 
redis.testOnBorrow=false
#\u5F53\u5BA2\u6237\u7AEF\u95F2\u7F6E\u591A\u957F\u65F6\u95F4\u540E\u5173\u95ED\u8FDE\u63A5\uFF0C\u5982\u679C\u6307\u5B9A\u4E3A0\uFF0C\u8868\u793A\u5173\u95ED\u8BE5\u529F\u80FD
redis.timeout=10000

测试代码:


业务数据缓存

Redis的其他业务使用场景 (用户注册功能)

​ 用户填写自己的手机号码,在页面中进行点击获取验证码的请求(按钮).系统会根据用户填写的手机号向该手机号码发送一个系统生成随机验证码给用户.用户根据手机收到的短信验证码在系统页面中填写响应的验证码内容后再次请求到系统中进行验证确认.

Redis主从复制

​ 在一般情况下Redis 只能作為一個單機內存數據庫,一旦服務器宕機即不能提供服務,即便能通過持久化策略重啟恢復數據,往往也做不到百分之百還原。再一個就是,單機的 Redis 需要處理所有的客戶端請求,包括讀和寫操作,壓力很大。

​ 主從複製技術是實現 Redis 集群的最基本架構,集群中有一臺或多臺主節點服務器(master),多臺從節點服務器(slave),slave 持續不斷的同步 master 上的數據。一旦 master 宕機,我們可以切換 salve 成為新的 master 穩定提供服務,也不用擔心 master 宕機導致的數據丟失。
在这里插入图片描述

Redis主从复制搭建

cp -R redis/ ./redis6380/

在这里插入图片描述

复制完后进入redis6380目录编辑redis.conf配置文件将端口进行更改
在这里插入图片描述

​ 修改完后在虚拟中有2个redis实例但端口不一致,可以进行分开启动进行测试2个redis是否可以分开启动
在这里插入图片描述
在这里插入图片描述

设置一个端口的redis为主节点一台为从节点

主节点的redis正常启动后,启动从节点服务,下面这个命令是在启动6380服务时设置指定6379节点的redis为主机进行复制

redis-server ./redis.conf --replicaof 192.168.25.3 6379

正常启动从节点redis后进入各个客户端通过命令进行主从状态

info replication

master信息:
在这里插入图片描述

slave信息:
在这里插入图片描述

哨兵模式

介绍

1.Sentinel(哨兵) 进程是用于监控 Redis 集群中 Master 主服务器工作的状态

2.在 Master 主服务器发生故障的时候,可以实现 Master 和 Slave 服务器的切换,保证系统的高可用(High Availability)

3.哨兵机制被集成在 Redis2.6+ 的版本中,到了2.8版本后就稳定下来了。

哨兵的功能

(1)集群监控:负责监控redis master和slave进程是否正常工作

**(2)消息通知:**如果某个redis实例有故障,那么哨兵负责发送消息作为报警通知给管理员

**(3)故障转移:**如果master node挂掉了,会自动转移到slave node上

**(4)配置中心:**如果故障转移发生了,通知client客户端新的master地址

哨兵工作

1.每个 Sentinel(哨兵)进程以每秒钟一次的频率向整个集群中的 Master 主服务器,Slave 从服务器以及其他 Sentinel(哨兵)进程发送一个 PING 命令。

2.如果一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 选项所指定的值, 则这个实例会被 Sentinel(哨兵)进程标记为主观下线SDOWN)。

3.如果一个 Master 主服务器被标记为主观下线(SDOWN),则正在监视这个 Master 主服务器的所有 Sentinel(哨兵)进程要以每秒一次的频率确认 Master 主服务器的确进入了主观下线状态

4.当有足够数量的 Sentinel(哨兵)进程(大于等于配置文件指定的值)在指定的时间范围内确认 Master 主服务器进入了主观下线状态(SDOWN), 则 Master 主服务器会被标记为客观下线(ODOWN)

5.在一般情况下, 每个 Sentinel(哨兵)进程会以每 10 秒一次的频率向集群中的所有Master 主服务器、Slave 从服务器发送 INFO 命令。

6.当 Master 主服务器被 Sentinel(哨兵)进程标记为**客观下线(ODOWN)**时,Sentinel(哨兵)进程向下线的 Master 主服务器的所有 Slave 从服务器发送 INFO 命令的频率会从 10 秒一次改为每秒一次。

7.若没有足够数量的 Sentinel(哨兵)进程同意 Master 主服务器下线, Master 主服务器的客观下线状态就会被移除。若 Master 主服务器重新向 Sentinel(哨兵)进程发送 PING 命令返回有效回复,Master 主服务器的主观下线状态就会被移除。
在这里插入图片描述

集群模式(重点)

Redis Cluster 是 Redis 的分布式解决方案,在 3.0 版本正式推出,有效地解决了 Redis 分布式方面的需求。

Redis Cluster 一般由多个节点组成,节点数量至少为 6 个才能保证组成完整高可用的集群,其中三个为主节点,三个为从节点。三个主节点会分配槽,处理客户端的命令请求,而从节点可用在主节点故障后,顶替主节点。
在这里插入图片描述
​ 该集群中包含 6 个 Redis 节点,3主3从,分别为M1,M2,M3,S1,S2,S3。除了主从 Redis 节点之间进行数据复制外,所有 Redis 节点之间采用 Gossip 协议进行通信,交换维护节点元数据信息。一般来说,主 Redis 节点会处理 Clients 的读写操作,而从节点只处理读操作.

Redis集群模式搭建

port 6380
cluster-enabled yes
cluster-config-file /usr/local/redis/rediscluster/redis6380/nodes-6380.conf
cluster-node-timeout 5000
protected-mode no
appendonly yes
daemonize yes
dir /usr/local/redis/rediscluster/redis6380/

​ 每个redis实例文件目录下都需要创建一个redis.conf并且端口要和这个实例端口一致,创建完成后通过脚本进行启动6台redis服务,成功启动后随意进入一个端口的redis实例进行查看当前目录:
在这里插入图片描述

创建集群

当6台redis服务启动后执行下面的命令

redis-cli --cluster create 192.168.25.126:6380 192.168.25.126:6381 192.168.25.126:6382 192.168.25.126:6383 192.168.25.126:6384 192.168.25.126:6385 --cluster-replicas 1

在这里插入图片描述

集群模式创建完成
在这里插入图片描述

进入redis节点,进入节点后查看节点信息
在这里插入图片描述
在这里插入图片描述

redis集群后不再有数据库的概念,单机redis有16个数据库,从0-15号.

集群没有redis数据库的概念不存在物理库0 username 1 username
哈希槽来维护存储数据

当集群创建完成后,redis会通过主节点来进行分配维护一段区间内的数据槽点0-16383. 通过连接redis后进行数据的存放或获取时都是通过一样的算法来定位该数据的槽点位置,如果获取/存放一个key没有在自己连接的机器节点时redis会自动重定向到维护该key所在机器上

Redis 集群使用数据分片(sharding)而非一致性哈希(consistency hashing)来实现: 一个 Redis 集群包含 16384 个哈希槽(hash slot), 数据库中的每个键都属于这 16384 个哈希槽的其中一个, 集群使用公式 CRC16(key) % 16383 来计算键 key 属于哪个槽, 其中 CRC16(key) 语句用于计算键 key 的 CRC16 校验和

CRC16(key)% 16384数值才是进行维护槽位
相似的key在进行计算后可能会落在一个槽位中,在集群后客户端可以连接任意的节点只有当进行数据操作时,redis会进行key的计算如果操作的key没有在自己锁维护的机器中可以进行将连接重定向到目标维护的节点机器上都是在主节点进行切换.从节点就是备份主的数据目的是当维护主节点发送宕机后从节点会升为主节点

由于redis集群对于key是hashSlot来进行维护的那么在进行key的使用时就不要在批量处理了

例如:keys * 只能获得当前节点下的所有key

当你的redis是集群部署后.对于业务操作特别多时尤其在redis同一个业务上操作量很大时要考虑类型来减少redis直接的重定向!

在这里插入图片描述
在这里插入图片描述

节点宕机测试

在这里插入图片描述

redis集群后不是通过ip和端口来进行维护身份的,如果集群中节点的(ip+端口)信息有变化时不会影响集群的身份连接

RedisTemplate用法

RedisTemplate常用方法

redisTemplate.hasKey(key)判断是否有key所对应的值,有则返回true,没有则返回false
redisTemplate.delete(key)删除单个key值
redisTemplate.delete(keys)其中keys:Collection keys
redisTemplate.dump(key)将当前传入的key值序列化为byte[]类型
redisTemplate.expire(key, timeout, unit)设置过期时间
redisTemplate.expireAt(key, date)设置过期时间
redisTemplate.keys(pattern)查找匹配的key值,返回一个Set集合类型
redisTemplate.rename(oldKey, newKey)返回传入key所存储的值的类型
redisTemplate.renameIfAbsent(oldKey, newKey)如果旧值存在时,将旧值改为新值
redisTemplate.randomKey()从redis中随机取出一个key
redisTemplate.getExpire(key)返回当前key所对应的剩余过期时间
redisTemplate.getExpire(key, unit)返回剩余过期时间并且指定时间单位
redisTemplate.persist(key)将key持久化保存
redisTemplate.move(key, dbIndex)将当前数据库的key移动到指定redis中数据库当中

redisTemplate.opsForValue() 方法

opsForValue.set(key, value)设置当前的key以及value值
opsForValue.set(key, value, offset)用 value 参数覆写给定 key 所储存的字符串值,从偏移量 offset 开始
opsForValue.set(key, value, timeout, unit)设置当前的key以及value值并且设置过期时间
opsForValue.setBit(key, offset, value)将二进制第offset位值变为value
opsForValue.setIfAbsent(key, value)重新设置key对应的值,如果存在返回false,否则返回true
opsForValue.get(key, start, end)返回key中字符串的子字符
opsForValue.getAndSet(key, value)将旧的key设置为value,并且返回旧的key
opsForValue.multiGet(keys)批量获取值
opsForValue.size(key)获取字符串的长度
opsForValue.append(key, value)在原有的值基础上新增字符串到末尾
opsForValue.increment(key,double increment)以增量的方式将double值存储在变量中
opsForValue.increment(key,long increment)通过increment(K key, long delta)方法以增量方式存储long值(正值则自增,负值则自减)
opsForValue.multiSetIfAbsent(valueMap)如果对应的map集合名称不存在,则添加否则不做修改
opsForValue.multiSet(valueMap)设置map集合到redis

redisTemplate.opsForHash() 方法

opsForHash.get(key, field)获取变量中的指定map键是否有值,如果存在该map键则获取值,没有则返回null
opsForHash.entries(key)获取变量中的键值对
opsForHash.put(key, hashKey, value)新增hashMap值
opsForHash.putAll(key, maps)以map集合的形式添加键值对
opsForHash.putIfAbsent(key, hashKey, value)仅当hashKey不存在时才设置
opsForHash.delete(key, fields)删除一个或者多个hash表字段
opsForHash.hasKey(key, field)查看hash表中指定字段是否存在
opsForHash.increment(key, field, long increment)给哈希表key中的指定字段的整数值加上增量increment
opsForHash.increment(key, field, double increment)给哈希表key中的指定字段的整数值加上增量increment
opsForHash.keys(key)获取所有hash表中字段
opsForHash.values(key)获取hash表中存在的所有的值
opsForHash.scan(key, options)匹配获取键值对,ScanOptions.NONE为获取全部键对

redisTemplate.opsForList() 方法

opsForList.index(key, index)通过索引获取列表中的元素
opsForList.range(key, start, end)获取列表指定范围内的元素(start开始位置, 0是开始位置,end 结束位置, -1返回所有)
opsForList.leftPush(key, value)存储在list的头部,即添加一个就把它放在最前面的索引处
opsForList.leftPush(key, pivot, value)如果pivot处值存在则在pivot前面添加
opsForList.leftPushAll(key, value)把多个值存入List中(value可以是多个值,也可以是一个Collection value)
opsForList.leftPushIfPresent(key, value)List存在的时候再加入
opsForList.rightPush(key, value)按照先进先出的顺序来添加(value可以是多个值,或者是Collection var2)
opsForList.rightPushAll(key, value)在pivot元素的右边添加值
opsForList.set(key, index, value)设置指定索引处元素的值
opsForList.trim(key, start, end)将List列表进行剪裁
opsForList.size(key)获取当前key的List列表长度
opsForList.leftPop(key);
opsForList.leftPop(key, timeout, unit);
移除并获取列表中第一个元素(如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止)
opsForList.rightPop(key);
opsForList.rightPop(key, timeout, unit);
移除并获取列表最后一个元素
opsForList.rightPopAndLeftPush(sourceKey, destinationKey);
opsForList.rightPopAndLeftPush(sourceKey, destinationKey, timeout, unit);
从一个队列的右边弹出一个元素并将这个元素放入另一个指定队列的最左边
opsForList.remove(key, index, value);删除集合中值等于value的元素(index=0, 删除所有值等于value的元素; index>0, 从头部开始删除第一个值等于value的元素; index<0, 从尾部开始删除第一个值等于value的元素)

redisTemplate.opsForSet() 方法

add(key, values)添加元素
remove(key, values)移除元素(单个值、多个值)
pop(key)删除并且返回一个随机的元素
size(key)获取集合的大小
isMember(key, value)判断集合是否包含value
intersect(key, otherKey)获取两个集合的交集(key对应的无序集合与otherKey对应的无序集合求交集)
intersect(key, otherKeys)获取多个集合的交集(Collection var2)
intersectAndStore(key, otherKey, destKey)key集合与otherKey集合的交集存储到destKey集合中(其中otherKey可以为单个值或者集合)
intersectAndStore(key, otherKeys, destKey)key集合与多个集合的交集存储到destKey无序集合中
union(key, otherKeys)获取两个或者多个集合的并集(otherKeys可以为单个值或者是集合)
unionAndStore(key, otherKey, destKey)key集合与otherKey集合的并集存储到destKey中(otherKeys可以为单个值或者是集合)
difference(key, otherKeys)获取两个或者多个集合的差集(otherKeys可以为单个值或者是集合)
differenceAndStore(key, otherKey, destKey)差集存储到destKey中(otherKeys可以为单个值或者集合)
randomMember(key)随机获取集合中的一个元素
members(key)获取集合中的所有元素
randomMembers(key, count)随机获取集合中count个元素
distinctRandomMembers(key, count)获取多个key无序集合中的元素(去重),count表示个数
scan(key, options)遍历set类似于Interator(ScanOptions.NONE为显示所有的)
move(key,value,destKey)将指定元素从一个集合移动到另一个集合

redisTemplate.opsForZSet() 方法

add(K key, V value, double score)将一个成员值及其分数添加到有序集合中
add(K key, Set<ZSetOperations.TypedTuple> tuples)批量添加多个成员值及其分数到有序集合中
incrementScore(K key, V value, double delta)给指定成员的分数增加 delta 值,可以是负数来减少分数
rank(K key, Object value)获取指定成员在有序集合中的排名,排名从 0 开始,按照分数从小到大排序
reverseRank(K key, Object value)获取指定成员在有序集合中的倒序排名,排名从 0 开始,按照分数从大到小排序
range(K key, long start, long end)获取有序集合中指定排名范围内的成员列表,包括分数。范围是闭区间,即包括 start 和 end
reverseRange(K key, long start, long end)获取有序集合中指定倒序排名范围内的成员列表,包括分数
rangeByScore(K key, double min, double max)获取分数范围内的成员列表,可以指定最小和最大分数,包括边界
reverseRangeByScore(key, min, max)按照Score值查询集合中的元素,结果从小到大排序
reverseRangeByScoreWithScores(key, min, max)返回值为:Set<ZSetOperations.TypedTuple>
count(K key, double min, double max)获取分数范围内的成员数量
remove(K key, Object… values)从有序集合中移除一个或多个成员
removeRange(K key, long start, long end)根据排名范围移除成员
removeRangeByScore(K key, double min, double max)根据分数范围移除成员
size(K key)获取有序集合的成员数量
score(K key, Object value)获取指定成员的分数
rangeWithScores(K key, long start, long end)获取指定排名范围内的成员及其分数列表
reverseRangeWithScores(K key, long start, long end)获取指定倒序排名范围内的成员及其分数列表
unionAndStore(key, otherKey, destKey)获取key和otherKey的并集并存储在destKey中(其中otherKeys可以为单个字符串或者字符串集合)
intersectAndStore(key, otherKey, destKey)获取key和otherKey的交集并存储在destKey中(其中otherKeys可以为单个字符串或者字符串集合)
zCard(key)获取集合的大小
更多推荐

CH573-09-BLE蓝牙安卓应用二次开发——RISC-V内核BLE MCU快速开发教程

一、基础工程搭建在上一章最后一讲的BLE蓝牙例程中,我们使用了沁恒官方的BLE调试助手完成数据发送,接下来我们使用AndroidStudio完成一款简易的BLE调试助手。1、参考文章我这里参考了CSDN中的一位博主“摸爬滚打的程序媛”的文章以及对应文章中的AndroidStudioBLE应用工程的Demo。版权声明:链

MP3算法及代码例程

MP3(MPEG-1AudioLayerIII)是一种数字音频压缩算法,用于对音频进行高效的压缩。MP3算法能够显著减小音频文件的大小,同时保持较高的音质。以下是MP3算法的主要步骤:采样率转换:将输入音频信号的采样率转换为固定的值,通常为44.1kHz。这是因为人耳对于音频的感知范围大约在20Hz到20kHz之间,因

9.3.5网络原理(应用层HTTP/HTTPS)

一.HTTP:1.HTTP是超文本传输协议,除了传输字符串,还可以传输图片,字体,视频,音频.2.3.HTTP协议报文格式:a.首行,b.请求头(header),c.空行(相当于一个分隔符,分隔了header和body),d.正文(body).4.5.URL:唯一资源描述符(长度不限制).a.b.注意:查询字符串(qu

第29章_瑞萨MCU零基础入门系列教程之改进型环形缓冲区

本教程基于韦东山百问网出的DShanMCU-RA6M5开发板进行编写,需要的同学可以在这里获取:https://item.taobao.com/item.htm?id=728461040949配套资料获取:https://renesas-docs.100ask.net瑞萨MCU零基础入门系列教程汇总:https://b

【初阶数据结构】树(tree)的基本概念——C语言

目录一、树(tree)1.1树的概念及结构1.2树的相关概念1.3树的表示1.4树在实际中的运用(表示文件系统的目录树结构)二、二叉树的概念及结构2.1二叉树的概念2.2现实中真正的二叉树2.3特殊的二叉树2.4二叉树的性质2.5二叉树的存储结构一、树(tree)1.1树的概念及结构树是一种非线性的数据结构,它是由n(

Softing物联网(IoT)方案之OT/IT数据集成

一利用数据提高效率和绩效多年以来数据集成和工业物联网一直在推动着市场的发展,目前我们已经能够集成并成功使用先进的技术、大量的传感器和复杂的数据格式等。而在工业物联网或工业4.0中,还有运营技术(OT)和信息技术(IT)它们之间的无缝数据交换对于企业提升竞争力而言同样非常重要。将生产和业务数据深度集成到IT层中可为新的利

【Oracle】Oracle系列--Oracle数据类型

文章目录前言1.字符类型2.数字类型3.大对象类型4.时间及时间间隔类型5.其他类型前言ORACLE基本数据类型,又叫内置数据类型(built-indatatypes)可以按类型分为:字符串类型、数字类型、大对象类型(LOB类型)、日期类型、LONGRAW&RAW类型、ROWID&UROWID类型。1.字符类型数据类型

浅说 MySQL 数据库日志有哪些?作用是什么?

目录1.MySQL日志有哪些?2.各种日志分析2.1错误日志2.2二进制日志2.3通用查询日志2.4慢查询日志2.5中继日志2.6数据定义语句日志2.7补充点3.日志有什么用(优点)4.日志的弊端1.MySQL日志有哪些?MySQL数据库为我们提供了很多种不同类型的日志文件,用来存储不同类型的日志。主要有错误日志,二进

Redis+SpringBoot企业版集群实战------【华为云版】

目录安装复制及集群bgsaverdbaofSpringBoot+Redis操作操作string操作hash操作set操作sortedset获取所有key&删除设置key的失效时间SpringDataRedis整合使用哨兵机制安装下载地址Redis上传至服务器解压tarzxvfredis-5.0.3.tar.gz安装依赖

JS Ajax 封装

ajax封装一、什么是Ajax?二、Ajax的优缺点?2.1优点2.2缺点三、Ajax的使用3.1状态码3.2xhr的基本使用3.3ajax原生封装:3.3.1触发GET请求:3.3.2调用POST请求:四、Ajax的约束一、什么是Ajax?Ajax(AsynchronousJavaScriptAndXML)是2005

【C++杂货铺】国庆中秋特辑——多态由浅入深详细总结

文章目录一、多态的概念二、多态的定义及实现2.1多态的构成条件2.2虚函数2.3虚函数的重写2.4虚函数重写的两个例外2.4.1协变(基类与派生类虚函数返回值类型不同)2.4.2析构函数的重写(基类与派生类析构函数的名字不同)2.5C++11override和final2.5.1final:修饰虚函数,表示该虚函数不能

热文推荐