当前位置: 首页 > news >正文

Redis 基础总结

在这里插入图片描述

1、NoSQL概述

1.1 数据库分类

目前数据库分:关系型数据库与非关系型数据库

常用的关系型数据库: Oracle,MySQL,SqlServer,DB2

常用的非关系数据库:Redis,MongoDB,ElasticSearch, Hbase,Neo4j

那啥是非关系数据库呢?此处涉及到新名词:NoSQL

NoSQL最常见的解释是“non-relational”, “Not Only SQL”也被很多人接受。NoSQL仅仅是一个概念,泛指非关系型的数据库,区别于关系数据库,它们不保证关系数据的ACID特性。详情见:百度百科:https://baike.baidu.com/item/NoSQL/8828247?fr=aladdin

1.2 为什么诞生NoSQL

随着互联网 web2.0 网站的兴起,非关系型的数据库现在成了一个极其热门的新领域,系数据库产品的发展非常迅速,而传统的关系型数据库在应付 web2.0 网站,特􏰂是超大规 模和高并发的 SNS 类型的 web2.0 纯动态网站已经显得力不从心,暴露了很多难以克服的问题,比如高并发-高效率-高扩展

1 、 Highperformance- 对数据库高并发读写的需求

web2.0 网站要根据用户个性化信息来实时生成动态页面和提供动态信息,所以基本上无法使用动态页面静态化技术,因此数据库并发负载非常高,往往要达到每秒上万次读写请求。关系型数据库应付上万次 SQL 查询还勉强顶得住,但是应付上万次 SQL 写数据请求,硬盘IO 就已经无法承受了,其实对于普通的 BS 网站,往往也存在对高并发写请求的需求。

2 、HugeStorage- 对海量数据的高效率存储和访问的需求

对于大型的 SNS 网站,每天用户产生海量的用户动态信息,以国外的 Friend feed 为例,一个月就达到了 2.5 亿条用户动态,对于关系数据库来说,在一张 2.5 亿条记录的表里面进行SQL 查询,效率是极其低下乃至不可忍受的。再例如大型 web 网站的用户登录系统,例如腾讯,盛大,动辄数以亿计的帐号,关系数据库也很难应付。

3、HighScalability&&HighAvailability- 对数据库的高可扩展性和高可用性的需求

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

1.3 NoSQL和关系数据库的区别

在关系型数据库数据都是存放在表中,有分类存放,连接查询,主键,外键等概念

NoSQL泛指非关系型数据库,采用区别于关系型数据库的设计,主要是针对关系型数据库性能瓶颈来设计的,专门处理关系型数据库不擅长做的业务场景,不同的NoSQL针对的点不一样, 比如redis适合做缓存 , Neo4J 适合做图片服务器.

在这里插入图片描述

2、Redis概述

2.1 Redis简介

是以key-value形式存储,和传统的关系型数据库不一样.不一定遵循传统数据库的一些基本要求.(非关系型的,分布式的,开源的,水平可拓展的)

优点:
对数据高并发读写(直接是内存中进行读写的)
对海量数据的高效率存储和访问
对数据的可拓展性和高可用性.
单线程操作,每个操作都是原子操作,没有并发相关问题(Redis 6)

缺点:
Redis(ACID处理非常简单)
无法做太复杂的关系数据库模型

在这里插入图片描述
*

2.2 谁在用Redis

比较著名的公司有:
github、blizzard、stackoverflow、flickr

国内:
新浪微博(全球最大的Redis集群)【2017】
2200+亿 commands/day 5000亿Read/day 500亿Write/day
18TB+ Memory
500+ Servers in 6 IDC 2000+instances
淘宝
腾讯微博

2.3 怎么学Redis

Redis在线入门 : http://try.Redis.io/
Redis 中文资料站: http://www.Redis.cn/
https://www.runoob.com/Redis/Redis-tutorial.html

2.4 Redis的安装

题外话:

Redis是使用C写的程序,目前主流在Linux操作系统,官方不提供Window版,最新的Redis版:Redis7.x

官网下载:https://Redis.io/download/

Redis 的Window版是微软公司自行移植的,目前最新版:Redis-x64-3.2.100

window版:https://github.com/microsoftarchive/Redis/releases/tag/win-3.2.100

新版控的同学:

1>购买阿里云Redis

https://www.aliyun.com/minisite/goods?
2>购买阿里云ECS

购买服务器,自己搭建最新版的Redis

3>安装虚拟机:Linux,再安装最新版Redis

这个,项目三讲Linux操作系统时再教。

2.4.1服务端

版本:Redis-x64-3.2.100.msi

傻瓜式安装,下一步,下一步就可以了

注意:添加到环境变量中

在这里插入图片描述
*

注意:默认端口

在这里插入图片描述

注意:最大内存

在这里插入图片描述

测试是否成功

在这里插入图片描述
*

在这里插入图片描述
*

2.4.2客户端–Redisclient

打开CMD命令框,输入命令:java -jar Redisclient.jar

在这里插入图片描述

2.4.3客户端–RedisDesktopClient

在这里插入图片描述

2.4.4客户端–rdm

在这里插入图片描述

3、数据类型

3.1 概况

Redis支持的存储数据类型有很多:

常用:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)

不常用:HyperLogLog,Bitmap(位图),Bloom Filter(布隆过滤器),Geospatial(地理位置) ,Module(模块), Streams(流信息)

此处重点讲解常用的类型。

命令格式

类型命令 key 参数数据

set name dafei

操作建议

Redis操作有点类似Java的Map集合,都是key-value形式存储数据,在学习过程中,可以进行类比。

另外Redis中的key大部分为String类型,value值根据缓存数据结构可以选用:string,hash,list,set,zset等类型。

注意:下面讲的各种类型,表述的是缓存数据的value类型。

3.2 String类型

String类型包含多种类型的特殊类型,并且是二进制安全的,其值可以是数值,可以是字符串,也可以是二进制数据。

类似Java中:Map<String, String/int> map

在Redis内容数据存储结构:

在这里插入图片描述

3.2.1 常用的命令

命令格式功能案例
set key value将key-value缓存redis中set name dafei
get key从redis中获取key对应value值get name
incr key将key对应value值 + 1incr age
decr key将key对应value值-1decr age
setex key seconds value将key-value缓存到redis中,seconds 秒后失效setex sex 10 man
ttl key查看key存活时间ttl sex
del key从redis中删除keydel name
setnx key value如果key已经存,不做任何操作,如果key不存,直接添加setnx name xiaofei

3.2.2 非常用命令

命令格式功能案例
incrby key increment给key对应值加incrementincrby age 10
mset k1 v1 k2 v2…批量添加k1v1 k2v2 key value对mset name dafei age 18
mget k1 k2…批量获取k1, k2的值mget name age
append key value在key对应的value值中拼+valueappend name yes
setrange key offset value修改key对应的value值,替换为指定value,冲offset索引位置开始setrange name 2 xx

3.2.3 应用场景

1>计数器

如:视频播放数系统就是使用Redis作为视频播放数计数的基础组件。

incr viewnum 1

2>共享session:

出于负载均衡的考虑,分布式服务会将用户信息的访问均衡到不同服务器上,用户刷新一次访问可能会需要重新登录,为避免这个问题可以用Redis将用户session集中管理, 在这种模式下只要保证Redis的高可用和扩展性的,每次获取用户更新或查询登录信息都直接从Redis中集中获取。

在这里插入图片描述

user_login_info:uid---->{“id”:1, “name”:“dafei”, “age”:18}

3.3 Hash类型

Hash类型是String类型的field和value的映射表,或者说是一个String集合。它特别适合存储对象,相比较而言,将一个对象存储在Hash类型里要比存储在String类型里占用更少的内存空间。

类似Java中:Map<String, Map<String, ?>> map

在这里插入图片描述
*

3.3.1 常用的命令

命令格式功能案例
hset key field value将field value对缓存到redis中hash中,键值为keyhset user name dafei
hget key field从key对应hash列表中获取field字段hget user name
hexists key field判断key对应的hash列表是否存在 field字段hexists user age
hdel key field删除key对应hash列表中field字段hdel user age
hincrby key field increment给key对应hash列表中field字段 + incrementhincrby user age 10
hlen key查看key对应的hash列表field的数量hlen user
hkeys key获取key对应的hash列表所有的field值hkeys user
hvals key获取key对应的hash列表所有的field对应的value值kvals user
hgetall key获取key对应的hash列表中所有的field及其对应的value值hgetall user

3.3.2 应用场景

Hash结构相对于字符串序列化缓存信息更加直观,并且在更新操作上更加便捷。

共享session设计

public class User{private String userame;private String password;private  int age;
}

登录用户:

User user = new User("dafei", "666", 18);

登录缓存:

key:user_token value:new User(“dafei”, “666”, 18)

-------------------------------------------------------------------------------------

方案1: 将user对象转换json格式字符串存Redis 【侧重于查, 改非常麻烦】

key value

-------------------------------------------------------------------------------------

user_token“{name:dafei, age:18, password:666}”

方案2: 将user对象转换hash对象存Redis【侧重于改,查询相对麻烦】

key value

-------------------------------------------------------------------------------------

user_token{

name:ddafei

age : 18

password: 666

}

3.4 List类型

Redis中的List类似Java中的Queue,也可以当做List来用.

List类型是一个链表结构的集合,其主要功能有push、pop、获取元素等,更详细的说,List类型是一个双端链表的结构,我们可以通过相关操作进行集合的头部或者尾部添加删除元素,List的设计非常简单精巧,即可以作为栈,又可以作为队列,满足绝大多数需求.

类似Java中:Map<String, List> map

在这里插入图片描述
*

3.4.1 常用的命令

命令格式功能案例
rpush key value从右边往key集合中添加value值rpush hobby java
lrange key start stop从左边开始列表key集合,从start位置开始,stop位置结束lrange hobby 0 -1
lpush key value从左边往key集合中添加value值lpush hobby c++
lpop key弹出key集合中最左边的数据lpop hobby
rpop key弹出key集合中最右边的数据rpop hobby
llen key获取列表长度llen hooby

3.4.2 非常用命令

命令格式功能案例
linsert key before pivot value操作key集合,在pivot值之前插入valuelinsert hobby before java c#
linsert key after pivot value操作key集合,在pivot值之后插入valuelinsert hobby after java c#
lset key index value操作key集合,更新索引index位置值为valuelset hobby 1 go
lrem key count value操作key集合,删除 count个 value值lrem hobby 3 go
ltrim key start stop操作key集合,从start到stop截取自列表ltrim hobby 2 4
lindex key index操作key集合,获取索引为index位置的数据lindex hobby 1

3.4.3应用场景

1>用户收藏文章列表:

key:user_favor_article_list

value: [aid1, aid2, aid3…]

3.5 Set类型

Set集合是String类型的无序集合,set是通过HashTable实现的,对集合我们可以取交集、并集、差集。

类似Java中:Map<String, Set> map

在这里插入图片描述
*

3.5.1 常用的命令

命令格式功能案例
sadd key members […]往key 集合中添加member元素sadd myset a b c
smembers key遍历key集合中所有的元素smembers myset
srem key members […]删除key集合中members元素srem myset a
spop key count从key集合中随机弹出count个元素spop myset 1

3.5.2 非常用命令

命令格式功能案例
sdiff key1 key2返回key1中特有的元素(差集)sdiff key1 key2
sdiffstore dest key1 key2返回key1中特有的元素,并将返回值缓存到dest集合中sidiffstore dest key1 key2
sinter key1 key2返回key1跟key2集合的交集sinter key1 key2
sinterstore dest key1 key2返回key1跟key2集合的交集,并将返回值缓存到dest集合中sinterstore dest key1 key2
sunion key1 key2返回key1跟key2集合的并集sunion key1 key2
sunionstore dest key1 key2返回key1跟key2集合的并集,并将返回值缓存到dest集合中sunionstore dest key1 key2
smove source destination member将source集合中member元素移动到destination集合中smove key1 key2 aa
sismember key member判断member元素是否在key集合中sismember key1 aa
srandmember key count随机获取set集合中count 个元素srandmember key1 1

3.5.3 应用场景

1,去重;

2,抽奖;

​ 1:准备一个抽奖池:sadd luckydraw 1 2 3 4 5 6 7 8 9 10 11 12 13

​ 2:抽3个三等奖:spop luckydraw 3

​ 3:抽2个二等奖:spop luckydraw 2

​ 4:抽1个:一等奖:spop luckydraw 1

3.6 Sorted set 类型

Sorted set 也称Zset类型,是一种具有排序效果的set集合。它跟set集合一样也是 string 类型元素的集合,且不允许重复的成员。并且要求每个元素都会关联一个double 类型的分数。后续可以通过分数来为集合中的成员进行从小到大的排序。

Sorted set集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。 集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。

数据缓存结构:

在这里插入图片描述

3.6.1 常用的命令

命令格式功能案例
zadd key score member往key集合中添加member元素,分数为scorezadd players 100 a
zincrby key increment member将key集合中的member元素 分数 + incrementzadd players 100 a
zrange key start stop [withscores]将key集合中的元素按分数升序排列 [显式分数]zrange players 0 -1 withscores
zrevrange key start stop [withscores]将key集合中的元素按分数降序排列 [显式分数]zrevrange players 0 -1 withscores
zrank key member返回member元素在key结合中的正序排名zrank players a
zrevrank key member返回member元素在key结合中的倒序排名zrevrank players a
zcard key返回key集合元素个数zcard players

3.6.2 非常用命令

命令格式功能案例
zrangebyscore key min max [withscores]按[min, max) 分数范围返回key集合中元素(正序)zrangebyscore players 200 300 withscores
zrevrangebyscore key min max [withscores]按[min, max) 分数范围返回key集合中元素(倒序)zrevrangebyscore players 200 300 withscores
zrem key member删除key集合中member元素与分数zrem players a
zremrangebyscore key min max withscores按[min, max) 分数范围删除key集合中元素zremrangebyscore players 200 300 withscores
zremrangebyrank key start stop删除key集合正序排名落在[start, stop) 范围元素zremrangebyrank players 10 20
zcount key min max按照分数范围[min, max]统计key集合中元素个数zcount players 100 300

3.6.3 应用场景

排行榜:有序集合经典使用场景。例如视频网站需要对用户上传的视频做排行榜,榜单维护可能是多方面:按照时间、按照播放量、按照获得的赞数等。

3.7 类型总结

一个问题,Redis在项目中如何使用?

思考点:

1>项目是否需要使用到缓存?使用

2>使用缓存是否选用Redis?选用

3>使用Redis那该怎么设计Key-Value值?

这里重点讨论Redis的KV对的设计。

3.7.1 Value设计

先说value值的设计其实就是value类型选用: String, Hash, List, Set, Sort Set

一般考虑:

  • 是否需要排序?要使用Sort Set
  • 缓存的数据是多个值还是单个值,
  • 多个值:允许重复选List 不允许重复选择Set
  • 单个值:简单值选择String, 对象值选择Hash

一种取巧的方式:

  • 是否需要排序?要使用Sort Set
  • 剩下使用String

操作方式:

所有value之后都转换成json格式字符串,然后缓存到Redis,原因:Java操作方便,减少泛型操作麻烦

比如:

List<String>list = ...
Set<String> set = ....
Map<String, Object> map = ....List<Object>  list = Redis对象.getList
Set<Object> set =Redis对象.getSet   
Map<Object, Object> map  =  Redis对象.getMap

不管存放啥数据类型,从reds中获取出来都是Object类型,后续对象强制转换麻烦,干脆直接使用字符串。

3.7.2 Key设计

Redis 的key 设计讲究4个性:

唯一性

Redis 类似Map集合,key必须保证唯一,缓存同一个key时,后者会覆盖前者,所有必须要求唯一,那如何保证唯一呢?

最常用的方式:使用缓存数据的主键作为key

比如:缓存员工信息

key value

----------------------------------------------------------------

1 员工1

2 员工2

其中的1, 2 是员工的id

可读性

可读性是保证Redis的key能做到见名知意,上面的员工id1, 员工id2 虽说能保证key唯一,但可读性非常差,维护key时,无法从, 1, 2中快速判断该key对应value值。所以一一般在保证key唯一的前提下,给key加上前缀:

key value

----------------------------------------------------------------

employee_info:id1 员工1

employee_info:id2 员工2

employee_info:id1 employee_info:id2 这样子设计key,可读性就好多了。

可读性前缀的设计规范千奇百怪,我个人比较推崇的:

  • 普通单值

    key value

    ----------------------------------------------------------------

    employe_info:id1 员工对象信息

  • 类似关系型数据库设计

    表名:主键名:主键值:列名

    key value

    ----------------------------------------------------------------

    employee : id : 1:info 员工对象信息

  • 通用玩法

    业务模块名:业务逻辑含义:其他:value类型

    key value

    -----------------------------------------------------------------------

    employee :base.info:id1:hash 员工对象信息

    业务模块名:表示该key属于哪个功能模块

    业务逻辑含义段:这里可以使用 . 分开, 具体业务逻辑表示

    ​ 比如:缓存员工权限

    ​ employee:auth.permission:id1:set 员工权限集合

    其他:一般设置唯一标识,比如主键

    value类型:key对应value类型值,提高可读性。

灵活性

这个难介绍,一般key保证唯一时,可以使用主键,有的使用,一个主键不能表达出全部意思,可以使用联合主键。

比如:

id为1的朋友圈下id为A的评论。

key value

-----------------------------------------------------------------------

post:1:reply:A 评论内容

post:1:reply:B 评论内容

时效性

Redis key一定要设置过期时间。要跟自己的业务场景,需要对key设置合理的过期时间。可以在写入key时,就要追加过期时间;也可以在按照需要动态设置。

这里要注意:

  • 不设置过期时间,这种key为永久key,会一直占用内存不释放,时间久了,数量一多,就容易达到服务器的内存上限,导致宕机,开发时一般配合Key过期策略使用哦。
  • key的时效性设置,必须根据业务场景进行评估,设置合理有效期;

4、 Redis全局命令

全局命令针对的是所有的key,大部分用来做运维,做管理的

常用的全局key

命令格式功能案例
keys pattern按照pattern 匹配规则,列表redis中所有的keykeys xxx:*
exists key判断key是否存在exists name
expire key seconds给key设置过期时间,超时:secondsexpire name 10
persist key取消key过期时间persist name
select index切换数据库,默认是第0个,共有【0,15】个select 0
move key db从当前数据库将key移动到指定db库move name 1
randomkey随机返回一个keyrandomkey
rename key newkey将key改名为newkeyrename name newname
echo message打印message信息echo message
dbsize查看key个数dbsize
info查看redis数据库信息info
config get *查看所有redis配置信息config get *
flushdb清空当前数据库flushdb
flushall清空所有数据库flushall

5、 Redis安全性

因为Redis速度非常快,所以在一台比较好的服务器下,一个外部用户在一秒内可以进行15w次的密码尝试,这意味你需要设定非常强大的密码来方式暴力破解。此时就需要对Redis进行密码设置啦。

Linux系统

编辑 Redis.conf文件,找到下面进行保存修改
requirepass 自定义密码

重启Redis服务,访问时,使用带密码的命令:

Redis-cli -a 自定义密码

否则会提示: (error)NOAUTH Authentication required.

Window系统

跟Linux系统一样,区别是,window系统的文件是

Redis.window-service.config

6、 Redis编程

6.1 概况

Redis编程就是使用编程方式操作Redis,当前Redis支持的编程语言有:https://Redis.io/docs/clients/

在这里插入图片描述

这里以Java为开发语言,选择Java点击进去

在这里插入图片描述

java实现操作Redis的客户端有很多,其中名气最高的:RedissonJedislettuce 3个客户端,其中Jedis,lettuce侧重于单例Redis 数据库的 CRUD(增删改查),Redisson 侧重于分布式开发。当前重点讲解Jedis与lettuce的使用,后续有机会再重点讲解Redisson使用。

6.2 Jedis

项目使用的SpringBoot,所以重点讲解SpringBoot继承Jedis

步骤1:建项目,导入依赖

<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.4.3</version><relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>Redis.clients</groupId><artifactId>jedis</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency>
</dependencies>

步骤2:导入配置文件

#Redis配置--jedis版
jedis:pool:#Redis服务器的IPhost: localhost#Redis服务器的Portport: 6379#数据库密码password:#连接超时时间timeout: 7200#最大活动对象数maxTotall: 100#最大能够保持idel状态的对象数maxIdle: 100#最小能够保持idel状态的对象数minIdle: 50#当池内没有返回对象时,最大等待时间maxWaitMillis: 10000#当调用borrow Object方法时,是否进行有效性检查testOnBorrow: true#当调用return Object方法时,是否进行有效性检查testOnReturn: true#“空闲链接”检测线程,检测的周期,毫秒数。如果为负值,表示不运行“检测线程”。默认为-1.timeBetweenEvictionRunsMillis: 30000#向调用者输出“链接”对象时,是否检测它的空闲超时;testWhileIdle: true# 对于“空闲链接”检测线程而言,每次检测的链接资源的个数。默认为3.numTestsPerEvictionRun: 50

步骤3:加载配置文件

@Component
@ConfigurationProperties(prefix = "jedis.pool")
@Getter
@Setter
public class JedisProperties {private int  maxTotall;private int  maxIdle;private int  minIdle;private int  maxWaitMillis;private boolean  testOnBorrow;private boolean  testOnReturn;private int  timeBetweenEvictionRunsMillis;private boolean  testWhileIdle;private int  numTestsPerEvictionRun;private String host;private String password;private int port;private int timeout;
}

步骤4:编写Jedis配置类

@Configuration
public class JedisConfig {/*** jedis连接池* @param jedisProperties* @return*/@Beanpublic JedisPool jedisPool(JedisProperties jedisProperties) {JedisPoolConfig config = new JedisPoolConfig();config.setMaxTotal(jedisProperties.getMaxTotall());config.setMaxIdle(jedisProperties.getMaxIdle());config.setMinIdle(jedisProperties.getMinIdle());config.setMaxWaitMillis(jedisProperties.getMaxWaitMillis());config.setTestOnBorrow(jedisProperties.isTestOnBorrow());config.setTestOnReturn(jedisProperties.isTestOnReturn());config.setTimeBetweenEvictionRunsMillis(jedisProperties.getTimeBetweenEvictionRunsMillis());config.setTestWhileIdle(jedisProperties.isTestWhileIdle());config.setNumTestsPerEvictionRun(jedisProperties.getNumTestsPerEvictionRun());if (StringUtils.hasText(jedisProperties.getPassword())) {return new JedisPool(config, jedisProperties.getHost(), jedisProperties.getPort(),jedisProperties.getTimeout(), jedisProperties.getPassword());}return new JedisPool(config, jedisProperties.getHost(), jedisProperties.getPort(),jedisProperties.getTimeout());}
}

步骤5:编写测试类,实现测试

@SpringBootTest
public class JedisTest {@Autowiredprivate JedisPool jedisPool;@Testpublic void testConnection(){System.out.println(jedisPool);Jedis jedis = jedisPool.getResource();//需求:往Redis中添加kv对: name:dafeijedis.set("name", "dafei");System.out.println(jedis.get("name"));jedis.close();}
}

操作技巧:jedis中方法跟Redis中命令一样

6.3 Lettuce

Lettuce 之所以能流行,因为它抱了根好大腿-Spring-data。Spring-data-Redis底层就封装了Lettuce,接下来看下Springboot版的lettuce实现。

步骤1:导入依赖

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

步骤2:Redis配置

spring:Redis:host: 127.0.0.1port: 6379password: admin

步骤3:编写测试类,实现测试

@SpringBootTest
public class LettureTest {@Autowired//约定:// 操作Redis的key  是字符串// value是字符串类型或字符串类型元素private StringRedisTemplate template;@Testpublic void testRedis(){//name:dafeitemplate.opsForValue().set("name", "dafei");System.out.println(template.opsForValue().get("name"));// 操作string//template.opsForValue().xx();// 操作hash//template.opsForHash().xx();// 操作list//template.opsForList().xx();// 操作set//template.opsForSet().xx();// 操作zset//template.opsForZSet().xx();//spring-data-Redis  方法是Redis 命令全称//template.opsForList().rightPush()  //rpush//全局命令在template类上//template.keys("*");}
}

操作技巧:Lettuce中方法跟Redis中命令全称

7、Redis事务

一个事务从开始到执行会经历以下三个阶段:

  • 开始事务。
  • 命令入队。
  • 执行事务。

借用:菜鸟教程中例子

它先以 MULTI 开始一个事务, 然后将多个命令入队到事务中, 最后由 EXEC 命令触发事务, 一并执行事务中的所有命令:

Redis 127.0.0.1:6379> MULTI
OKRedis 127.0.0.1:6379> SET book-name "Mastering C++ in 21 days"
QUEUEDRedis 127.0.0.1:6379> GET book-name
QUEUEDRedis 127.0.0.1:6379> SADD tag "C++" "Programming" "Mastering Series"
QUEUEDRedis 127.0.0.1:6379> SMEMBERS tag
QUEUEDRedis 127.0.0.1:6379> EXEC
1) OK
2) "Mastering C++ in 21 days"
3) (integer) 3
4) 1) "Mastering Series"2) "C++"3) "Programming"

单个 Redis 命令的执行是原子性的,但 Redis 没有在事务上增加任何维持原子性的机制,所以 Redis 事务的执行并不是原子性的。

Redis事务可以理解为一个打包的批量执行脚本,但批量指令并非原子化的操作,中间某条指令的失败不会导致前面已做指令的回滚,也不会造成后续的指令不做。

127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set name dafei
QUEUED
127.0.0.1:6379(TX)> set age 18
QUEUED
127.0.0.1:6379(TX)> incr age 
QUEUED
127.0.0.1:6379(TX)> incr name
QUEUED
127.0.0.1:6379(TX)> get age
QUEUED
127.0.0.1:6379(TX)> get name
QUEUED
127.0.0.1:6379(TX)> exec
1) OK
2) OK
3) (integer) 19
4) (error) ERR value is not an integer or out of range
5) "19"
6) "dafei"
127.0.0.1:6379> 

Redis 事务可以一次执行多个命令, 并且带有以下三个重要的保证:

  • 批量操作在发送 EXEC 命令前被放入队列缓存。
  • 收到 EXEC 命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行。
  • 在事务执行过程,其他客户端提交的命令请求不会插入到事务执行命令序列中。

9、Redis持久化机制[拓展]

9.1 引言

先来一个小实验,大家可以一起实现一下

步骤1:在Redis中添加2个key-value对

127.0.0.1:6379> set aa aa
OK
127.0.0.1:6379> set bb bb
OK
127.0.0.1:6379> keys *

步骤2:重启Redis 服务器,在执行keys * 观察数据

步骤3:分析结果

会出现一下几种结果:

  • 之前的key在,aa bb 都在(最理想的结果)
  • 之前的key在,aa也在,bb不见了
  • 之前的key在,aa, bb 不在
  • 之前的key, aa, bb 都不在了(最坏的结果)

思考:

为啥会这样?以我们对内存的操作理解,按道理重启之后数据应该全丢失了,为啥Redis 可能丢失,也可能不丢失,为何?

这里就涉及到Redis的持久化机制了。

在这里插入图片描述
*

Redis持久化机制目前以后3种,分别为:

1>快照方式(RDB, Redis DataBase)

2>文件追加方式(AOF, Append Only File)

3>混合持久化方式(Redis4版本之后)

9.2 RDB方式

Snapshotting(快照)默认方式,将内存数据中以快照的方式写入到二进制文件中,默认为dump.rdb。触发RDB持久化过程分手动触发与自动触发。

触发机制

手动触发

使用save命令:会阻塞当前Redis服务器,知道RDB过程完成为主,如果内存数据较多,会造成长时间阻塞,影响其他命令的使用,不建议轻易使用

使用bgsave命令:Redis进程执行fork指令创建子进程,由子进程实现RDB持久化,有需要时建议使用bgsave命令。

自动触发

使用save相关配置,格式: save m n 表示m秒内数据集存在n次修改时会自动触发bgsave命令。

save 900 1  #900秒内如果超过1Key被修改则发起快照保存
save 300 10 #300秒内如果超过10个key被修改,则发起快照保存
save 60 10000

在这里插入图片描述
*

优点:

  • RDB快照文件是一个紧凑压缩的二进制文件,非常使用用于备份,全量复制等场景。开发中可以按照每6小时执行一次bgsave备份,用于容灾备份。

  • Redis加载RDB恢复数据远远快于AOF方式

缺点:

  • RDB无法做到实时持久化/秒级持久化,每次bgsave时都需要fork子进程,频繁执行有时间成本。
  • RDB快照文件不同版本格式不一样,容易引起兼容问题。

9.3 AOF方式

AOF与RDB不一样,它是一独立日志的方式记录每次写命令,重启时再重新执行AOF文件中命令达到恢复数据的目的。解决了数据持久化的实时性的问题。

Redis默认是不开启的,需要使用时,需要配置: appendonly yes

AOF 有3种文件同步策略

策略解释
appendfsync always收到命令就立即写到磁盘,效率最慢.但是能保证完全的持久化
appendfsync everysec每秒写入磁盘一次,在性能和持久化方面做了很好的折中
appendfsync no完全以依赖os,一般同步周期是30秒

在这里插入图片描述
*

优点:

  • AOF方式数据安全性更高,配置得当,最多损失1秒的数据量

  • 在不小心执行flushall命令,也可以通过AOF方式恢复(删除最后一个命令即可)

  • AOF 日志是一个增量日志文件,不会存在断电时出现损坏问题。即使出现问题,Redis-check-aof 工具也能够轻松修复它。

  • 当 AOF 变得太大时,Redis 能够在后台自动重写 AOF

缺点:

  • 相同数据量来说,AOF文件体积通常大于RDB文件
  • 数据持久化性能上来说,AOF 比 RDB 慢

9.4 RDB-AOF混合方式

混合持久化是结合了 RDB 和 AOF 的优点,在写入的时候,先把当前的数据以 RDB 的形式写入文件的开头,再将后续的操作命令以 AOF 的格式存入文件。即以 RDB 作为全量备份,AOF 作为增量备份,来提高备份效率。这样既能保证 Redis 重启时的速度,又能防止数据丢失的风险, 这就是 Redis 4.0 之后推出的 RDB-AOF 混合持久化模式,其作为默认配置来使用

9.5 持久化机制选择

  • 如果对数据安全性有非常高的要求,建议 RDB 和 AOF 同时启用。

  • 如果对数据安全性要求不是很高,能够容忍数据的丢失,建议单独使用 RDB。

  • 不推荐单独使用 AOF,因为对于进行数据库备份、更快重启以及 AOF 引擎中出现错误的情况来说,RDB 是更好的选择。

  • 如果没特殊要求,Redis又是4.x版本以上,可以选择RDB-AOF混合方式。

如果不是混合模式,而是普通的RDB与AOF一起启动时,Redis加载数据执行流程

在这里插入图片描述
*

10 、Redis内存淘汰机制

10.1 引言

Redis 启动会加载一个配置:

maxmemory <byte>   //内存上限

默认值为 0 (window版的限制为100M),表示默认设置Redis内存上限。但是真实开发还是需要提前评估key的体量,提前设置好内容上限。

此时思考一个问题,开发中,在设置完内存上限之后,如果Redis key达到上限了,该怎么办?这就设置到Redis的内存淘汰机制了。

10.2 内存淘汰算法

Redis内存淘汰机制也可以称之为key内卷机制,当资源不足时,该如何选择?

常见的内存淘汰机制分为四大类:

  • **LRU:**LRU是Least recently used,最近最少使用的意思,简单的理解就是从数据库中删除最近最少访问的数据,该算法认为,你长期不用的数据,那么被再次访问的概率也就很小了,淘汰的数据为最长时间没有被使用,仅与时间相关。

在这里插入图片描述

  • **LFU:**LFU是Least Frequently Used,最不经常使用的意思,简单的理解就是淘汰一段时间内,使用次数最少的数据,这个与频次和时间相关。

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • **TTL:**Redis中,有的数据是设置了过期时间的,而设置了过期时间的这部分数据,就是该算法要解决的对象。如果你快过期了,不好意思,我内存现在不够了,反正你也要退休了,提前送你一程,把你干掉吧。

  • 随机淘汰:生死有命,富贵在天,是否被干掉,全凭天意了。

10.3 Redis淘汰策略

Redis 通过配置

maxmemroy-policy  

来配置指定具体的淘汰机制,可供选择的值有:

通过maxmemroy-policy可以配置具体的淘汰机制,看了网上很多文章说只有6种,其实有8种,可以看Redis5.0的配置文件,上面有说明:

  • volatile-lru -> 找出已经设置过期时间的数据集,将最近最少使用(被访问到)的数据干掉。

  • volatile-ttl -> 找出已经设置过期时间的数据集,将即将过期的数据干掉。

  • volatile-random -> 找出已经设置过期时间的数据集,进行无差别攻击,随机干掉数据。

  • volatile-lfu -> 找出已经设置过期时间的数据集,将一段时间内,使用次数最少的数据干掉。

  • allkeys-lru ->与第1个差不多,数据集从设置过期时间数据变为全体数据。

  • allkeys-lfu -> 与第4个差不多,数据集从设置过期时间数据变为全体数据。

  • allkeys-random -> 与第3个差不多,数据集从设置过期时间数据变为全体数据。

  • no-enviction -> 什么都不干,报错,告诉你内存不足,这样的好处是可以保证数据不丢失

系统默认选择: noenviction

在这里插入图片描述

相关文章:

Redis 基础总结

1、NoSQL概述 1.1 数据库分类 目前数据库分&#xff1a;关系型数据库与非关系型数据库 常用的关系型数据库&#xff1a; Oracle&#xff0c;MySQL&#xff0c;SqlServer&#xff0c;DB2 常用的非关系数据库&#xff1a;Redis&#xff0c;MongoDB&#xff0c;ElasticSearch&…...

基于nginx的tomcat负载均衡和集群(超简单)

今天看到"基于apache的tomcat负载均衡和集群配置 "这篇文章成为javaEye热点。 略看了一下&#xff0c;感觉太复杂&#xff0c;要配置的东西太多&#xff0c;因此在这里写出一种更简洁的方法。 要集群tomcat主要是解决SESSION共享的问题&#xff0c;因此我利用memcac…...

ESIM实战文本匹配

引言 今天我们来实现ESIM文本匹配&#xff0c;这是一个典型的交互型文本匹配方式&#xff0c;也是近期第一个测试集准确率超过80%的模型。 我们来看下是如何实现的。 模型架构 我们主要实现左边的ESIM网络。 从下往上看&#xff0c;分别是 输入编码层(Input Ecoding) 对前…...

基于虚拟仿真技术的汽车燃油泵控制

在当前激烈的竞争环境下&#xff0c;汽车行业正在加速产业和技术更迭&#xff0c;整车厂对大型ECU嵌入式控制系统和软件的需求迫在眉睫。 然而&#xff0c;复杂而庞大的汽车系统往往由多个物理系统组成&#xff0c;系统所对应的模型都需要在不同的领域实现&#xff1a;发动机、…...

angular:HtmlElement的子节点有Shadow dom时奇怪的现象

描述&#xff1a; 这样写时&#xff0c;会自动跳过shadow dom节点的遍历 const cloneElement this.contentElement.cloneNode(true) as HTMLElement; for(let childNodeIndex 0; childNodeIndex < cloneElement.childNodes.length; childNodeIndex) {element.appendChild…...

栈与队列--删除字符串中的所有相邻重复项

给出由小写字母组成的字符串 S&#xff0c;重复项删除操作会选择两个相邻且相同的字母&#xff0c;并删除它们。 在 S 上反复执行重复项删除操作&#xff0c;直到无法继续删除。 在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。 示例&#xff1a; 输入&#x…...

使用SSH地址拉取远程仓库代码报下面的错误

说明&#xff1a;配置了SSH秘钥后&#xff0c;使用SSH地址克隆代码&#xff0c;依旧无法拉取代码&#xff0c;提示下面这个信息。 Their offer&#xff1a;ssh-rsa&#xff0c;ssh-dss fatal&#xff1a;Could not read from remote repository. Please make sure you have the…...

easycms v5.5 分析 | Bugku S3 AWD排位赛

前言 这个awd打的悲&#xff0c;后台默认用户名密码为admin:admin&#xff0c;但是几乎所有人都改了 而且一进去看到这个cms就有点懵逼&#xff0c;都不知道这个cms是干嘛的&#xff08;没用过相似的cms&#xff09; 虽然网上找出了很多相关的漏洞&#xff0c;但是不知道为什…...

成都营运《乡村振兴战略下传统村落文化旅游设计》许少辉八一著作

成都营运《乡村振兴战略下传统村落文化旅游设计》许少辉八一著作...

创邻科技Galaxybase助力SPG推动知识图谱应用落地

1. 知识图谱实践应用&#xff1a;从理论到落地的全景视角 知识图谱&#xff0c;作为一种先进的数据模型和信息表示策略&#xff0c;极大地提升了信息检索与分析的能力。该模型利用图结构&#xff0c;将不同领域、层次和类别的信息有机整合&#xff0c;令复杂的数据关系变得清晰…...

《TCP/IP网络编程》阅读笔记--域名及网络地址

目录 1--域名系统 2--域名与 IP 地址的转换 2-1--利用域名来获取 IP 地址 2-2--利用 IP 地址获取域名 3--代码实例 3-1--gethostbyname() 3-2--gethostbyaddr() 1--域名系统 域名系统&#xff08;Domain Name System&#xff0c;DNS&#xff09;是对 IP 地址和域名进行相…...

我的C#基础

using System; namespace HelloWorldApplication }TOC 欢迎使用Markdown编辑器 你好&#xff01; 这是你第一次使用 Markdown编辑器 所展示的欢迎页。 为帮助您在CSDN创作的文章获得更多曝光和关注&#xff0c;我们为您提供了专属福利&#xff1a; 已注册且未在CSDN平台发布过…...

【UnityShaderLab实现“Billboard“始终面向相机_播放序列图的效果_案例分享(内附源码)】

"Billboard"始终面向相机 Shader "billboard" {Properties{_MainTex ("Main Tex", 2D) = "white" {}_Color (...

Ceph入门到精通-S3 基准测试工具warp使用入门

S3 基准测试工具。 下载 下载适用于各种平台的二进制版本。 配置 可以使用命令行参数或环境变量配置 Warp。 可以使用 、 在命令行上指定要使用的 S3 服务器&#xff0c;也可以选择指定 TLS 和自定义区域。--host--access-key--secret-key--tls--region 也可以使用 、、 和…...

Docker--未完结

一.Docker是干什么的 在没亲自使用过之前&#xff0c;再多的术语也仅仅是抽象&#xff0c;只有写的人或者使用过的人能看懂。 所以&#xff0c;作为新手来说&#xff0c;只要知道Docker是用于部署项目就够了&#xff0c;下面展示如何用Docker部署项目及Docker常用命令。 二、…...

string的使用和模拟实现

&#x1f493;博主个人主页:不是笨小孩&#x1f440; ⏩专栏分类:数据结构与算法&#x1f440; C&#x1f440; 刷题专栏&#x1f440; C语言&#x1f440; &#x1f69a;代码仓库:笨小孩的代码库&#x1f440; ⏩社区&#xff1a;不是笨小孩&#x1f440; &#x1f339;欢迎大…...

基础算法---区间合并

直接上题目,不废话! 题目 给定 n 个区间 [l,r]&#xff0c;要求合并所有有交集的区间。 注意如果在端点处相交&#xff0c;也算有交集。 输出合并完成后的区间个数。 例如&#xff1a;[1,3] 和 [2,6] 可以合并为一个区间 [1,6]。 输入格式 第一行包含整数 n。 接下来 n 行&am…...

C++(day4)

思维导图 封装Mystring #include <iostream> #include<cstring>using namespace std;class Mystring{ public://无参构造函数Mystring():size(10){strnew char[size];strcpy(str,"");cout<<"无参构造函数"<<endl;}//有参构造函数…...

docker 部署 node.js(express) 服务

1、在 express 项目根目录下新增 Dockerfile 文件&#xff0c;内容如下&#xff1a; 创建服务容器的方法&#xff0c;可以根据自己的情况选择&#xff1a; 1、以下示例为宿主机没有安装 node 环境的写法&#xff1b; 2、先在本地构建包含 node 和 express 的基础镜像&#xff0…...

商城系统开发,如何确保用户数据的安全性?

确保用户数据的安全性是商城系统开发中至关重要的一项任务。随着数字化时代的到来&#xff0c;用户的个人信息和交易数据已成为黑客和不法分子的重要目标&#xff0c;因此保护用户数据的安全性对于商城系统的成功运营至关重要。在开发商城系统时&#xff0c;以下几个方面是确保…...

黑客必备工具Kali Linux,安装与使用教程全包含,从入门到精通,全网最详细全面的Kali Linux教程

Kali Linux是一个高级渗透测试和安全审计Linux发行版&#xff0c;目前可以说是网络安全人员的专用系统。 Kali Linux功能非常强大&#xff0c;能够进行信息取证、渗透测试、攻击WPA / WPA2保护的无线网络、离线破解哈希密码、将android、Java、C编写的程序反编译成代码等等&am…...

2024滴滴校招面试真题汇总及其讲解(二)

4.【基础题】HashMap了解吗?介绍一下它对应的线程安全版本。 HashMap 是 Java 中一种键值对映射的集合,它使用哈希表来存储键值对。HashMap 具有插入和删除元素效率高的优势,但不是线程安全的。 ConcurrentHashMap 是 Java 中一种线程安全的 HashMap,它使用分段锁来保证线…...

嵌入式-C语言中的if语句

目录 一.if语句介绍 二.案例实操 2.1C语言运行模板代码 2.2运行方法 2.3案例 一.if语句介绍 if判断语句是一种用于根据条件来进行条件分支的控制流语句。通过判断一个条件的真假来决定执行不同的代码块。if语句的基本语法如下&#xff1a;if (条件表达式) {// 如果条件为…...

组合数 rust解法

组合数。 编写函数&#xff0c;参数是两个非负整数n和m&#xff0c;返回组合数 C n m C_n^m Cnm​&#xff0c;其中m≤n≤25。 例如&#xff0c;n25&#xff0c;m12时答案为5200300。 解法&#xff1a; fn c(n: u32, m: u32)->u64 {let m if m > n-m {n-m}else{m};le…...

【SpringMVC】自定义注解与AOP结合使用

目录 一、SpringMVC之自定义注解 1.1 Java注解简介 1.2 为什么要用注解 1.3 注解的分类 ⭐ 1.3.1 JDK基本注解 1.3.2 JDK元注解 1.3.3 自定义注解 1.4 自定义注解三种使用案例 1.4.1 案例一&#xff08;获取类与方法上的注解值&#xff09; 1.4.2 案例二&#xff0…...

MyEclipse 用tomcat部署SSM项目后,项目名称和当前项目不一致

MyEclipse 用tomcat部署SSM项目后&#xff0c;项目成功启动&#xff0c;但是访问所有接口报404 从这里可以看到&#xff0c;部署的项目名为accurate_sugar_control_yc_api&#xff0c;但实际我们项目名字应该为accurate_sugar_control_otc_api 解决办法 在本地找到项目的根目…...

来喽!!炒鸡详细的“数据在内存中的存储”真的来喽!

目录​​​​​​​ 1. 整数在内存中的存储 1.1 ⼆进制介绍 1.1.1 2进制转10进制 1.1.2 10进制转2进制 1.1.3 2进制转8进制 1.1.4 2进制转16进制 1.2 原码、反码、补码 2. ⼤⼩端字节序和字节序判断 2.1 什么是⼤⼩端&#xff1f; 2.2 为什么有⼤⼩端? 2.3 练习 …...

【面试经典150 | 双指针】验证回文串

文章目录 写在前面Tag题目来源题目解读解题思路方法一&#xff1a;筛选判断方法二&#xff1a;原地判断 知识回顾回文串双指针字符串操作 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法&#xff0c;两到三天更新一篇文章&#xff0c;欢迎催更…… 专栏内容以分…...

sql存储引擎

-- 查询建表语句 --可以查看引擎 show create table account; -- 可以看到默认引擎 InnoDB ENGINEInnoDB -- 查看当前数据库支持得存储引擎 show engines ; # InnoDB 默认 存储引擎 # MyISAM sql早期默认 存储引擎 # MEMORY 存储在内存中 用来做临时表和缓存 存储引擎 …...

Visual Studio 2022安装SVN插件教程

1. 第一步&#xff1a;避免踩坑&#xff0c;超级重要&#xff01;&#xff01;&#xff01;关闭Visual Studio 2022应用程序&#xff1b;&#xff08;不然插件装不上&#xff0c;一直转圈&#xff01;&#xff09; 2.第二步&#xff1a;下载Visual Studio 2022版本对应的SVN插件…...

昆山建设局网站/seo一个月工资一般多少

Exchange Server 的2个日志目录会增长的很快&#xff0c;需要定时清理&#xff0c;不然C盘的空间很快就会吃光&#xff0c;以下这个powershell脚本就是用于清理目录下面的日志的&#xff0c;已在生产环境中测试过&#xff0c;没问题&#xff1a; Set-Executionpolicy RemoteSi…...

wordpress 邮箱发布/安徽搜索引擎优化

2009年&#xff0c;是我收获颇多的一年... 2010年呢&#xff1f; 本文转自远哥博客园博客&#xff0c;原文链接&#xff1a;http://www.cnblogs.com/taven/archive/2009/12/18/1627388.html&#xff0c;如需转载请自行联系原作者...

内蒙古兴泰建设集团信息化网站/seo建设招商

我知道这可能是有史以来最简单的问题。但是&#xff0c;我开始学习Tkinter&#xff0c;我不知道当鼠标单击GUI时如何引用事件。在当我点击画布时&#xff0c;我想画一些点。我不能在paint函数中引用canvas变量。在这段代码基于SO中的问题每当我尝试这个例子时&#xff0c;paint…...

厦门建设局地址/化工网站关键词优化

解决方法 https://blog.csdn.net/qwq1503/article/details/65916426 转载于:https://www.cnblogs.com/macT/p/10363970.html...

软件定制 开发/seo的含义是什么意思

jpg和png格式的图片在日常生活中是使用广泛的两种图片&#xff0c;那么如果想将这两种不同格式的静态图片合成一张gif动态图片的话&#xff0c;该如何来进行操作呢&#xff1f;下面教大家使用gif合成工具&#xff0c;轻松在线合成png和jpg图片动图制作的方法&#xff0c;有需求…...

杭州外贸网站建设公司排名/企业推广app

堆是什么&#xff1f; 是土堆吗&#xff1f; 那当然不是啦~ 堆是一种被看作完全二叉树的数组。 那么什么是完全二叉树呢&#xff1f; 如果二叉树中除去最后一层节点为满二叉树&#xff0c;且最后一层的结点依次从左到右分布&#xff0c;则此二叉树被称为完全二叉树。 堆的特…...