Redis

文章介绍了NoSQL数据库的概述,包括其非关系型特性以及四大分类:键值存储、列存储、文档型和图形数据库。接着深入讲解了Redis,一个内存型的Key-Value数据库,它的特点、安装步骤以及常用命令。文章还详细阐述了Redis的持久化机制,如RDB快照和AOF日志,并提到了如何通过Java操作Redis以及SpringBoot整合Redis的示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、NoSQL引言

**NoSQL**(` Not Only SQL` ),意即**不仅仅是SQL**, 泛指非关系型的数据库。

SQL  ----> 关系型数据库(mysql、oracle、sqlserver) 基于表 ,有关联关系,可持久化数据到硬盘,支持事务

NoSQL ----> 非关系型数据库 ,是键值对,基于文档的,图形数据库或宽列存储 ,没有事务

2、NoSQL的四大分类

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

说明:用到一个哈希表,这个表中有一个特定的键和一个指针指向特定的数据。
特点:简单、易部署,但对部分值进行查询或更新效率低

列存储数据库 (海量数据)

说明:通常用来应对分布式存储的海量数据,大数据领域
特点:键指向多个列

文档型数据库

说明:同键值存储类似(升级版),该类型的数据模型是版本化的文档,半结构化的文档以特定的格式存储,比如JSON。
特点:以文档形式存储,允许之间嵌套键值。且文档型数据库比键值数据库的查询效率更高

图形(Graph)数据库 (阿里云 OSS 对象存储 图片 视频 音频)

说明:使用灵活的图形模型,能够扩展到多个服务器上。
特点:没有标准的查询语言,进行数据库查询需要制定数据模型

3、Redis引言

Redis开源 ,遵循BSD ,基于内存数据存储,被用于作为 数据库、缓存、消息中间件

- 总结: redis是一个内存型的数据库    
- 特点:
-	 Redis是一个高性能key/value内存型数据库  
- 	 读写快
-	 Redis支持丰富的数据类型   String  list  hash set  zset  
-	 Redis支持持久化 (解决断电丢失内存数据)     内存数据    ---->    磁盘
-	 Redis单线程,单进程,线程安全

4、Redis安装

# 0.准备环境
- vmware15.x+
- centos7.x+

# 1.下载redis源码包
- https://redis.io/

# 2.下载完整源码包
- redis-4.0.10.tar.gz

# 3.将下载redis资料包上传到Linux中

# 4.解压缩文件
- [root@localhost ~]# tar -zxvf redis-4.0.10.tar.gz

# 5.安装gcc  
- yum install -y gcc

# 6.进入解压缩目录执行如下命令
- make MALLOC=libc

# 7.编译完成后执行如下命令
- make install PREFIX=/usr/redis

# 8.进入/usr/redis目录启动redis服务 
- ./redis-server

# 9.Redis服务端口默认是 6379

# 10.进入bin目录执行客户端连接操作
- ./redis-cli –p 6379
- ./redis-cli -p 7000 --raw //--raw 代表显示中文

5、Redis数据库相关指令

5.1 数据库操作指令

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

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

# 3.redis客户端显示中文
-	./redis-cli  -p 7000 --raw

5.2 操作key常用指令

# 1.DEL指令
- 语法 :  DEL key [key ...] 
- 作用 :  删除一个或多个key ,不存在的key 会忽略
- 返回值: 删除key 的数量

# 2.EXISTS指令
- 语法:  EXISTS key
- 作用:  key 是否存在
- 返回值: 若key 存在,返回1 ,否则返回0

# 3.KEYS
- 语法 :  KEYS pattern
- 作用 :  查找所有符合pattern 的key
- 语法:
	* :任意数量字符
	? :一个字符
	[]:括号内的任意值
- 返回值: 符合的key 列表

# 4.MOVE
- 语法 :  MOVE key db
- 作用 :  将当前数据库的key 移动到给定的数据库db 当中
- 返回值: 移动成功返回1 ,失败返回0 。

# 5.EXPIRE(PEXPIRE)
- 语法:  EXPIRE(PEXPIRE) key seconds
- 作用:  以秒(毫秒)为单位为key 设置生存时间,当key 过期(生存时间为0秒),自动删除
- 返回值:设置成功返回1,否则0

# 6.TTL(PTTL)
- 语法 :   TTL(PTTL) key
- 作用 :   以秒(毫秒)为单位,返回给定key 的剩余生存时间(TTL, time to live)
- 返回值:
	当key 不存在时,返回-2 
	当key 存在但没有设置剩余生存时间时,返回-1 
	否则,以秒为单位,返回key 的剩余生存时间

# 7.RANDOMKEY
- 语法 :  RANDOMKEY
- 作用 :  从当前数据库中随机返回(不删除) 一个key 。
- 返回值:当数据库不为空时,返回一个key 。当数据库为空时,返回nil 

# 8.RENAME
- 语法 :  RENAME key newkey
- 作用 :  将key 改名为newkey 。当key 和newkey 相同或key 不存在时,返回错误。当newkey 已经存在时覆盖旧值。
- 返回值: 改名成功时提示OK ,失败时候返回错误。

# 9.TYPE
- 语法 :  TYPE key
- 作用 :  返回key 所储存的值的类型。
- 返回值:
	none (key 不存在)、string (字符串)、list (列表)、set (集合)、zset (有序集)、hash (哈希表)

5.3 String类型常用命令

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

5.4 List类型(有序可重复)常用命令

命令说明
lpush (lpushx)将某个值加入到一个key列表头部 (key保证存在)
rpush(rpushx)将某个值加入到一个key列表末尾(key保证存在)
lpop (rpop)返回和移除列表左(右)边的第一个元素
lrange获取某一个下标区间内的元素
llen获取列表元素个数
lset设置某一个指定索引的值(索引必须存在)
lindex获取某一个指定索引位置的元素
lrem删除元素
ltrim保留列表中特定区间内的元素
linsert在某一个元素之前,之后插入新元素

5.5 Set类型(无序不可重复)常用命令

命令说明
sadd为集合添加元素
smembers无序显示集合中所有元素
scard返回集合中元素个数
spop随机返回一个元素 并将元素在集合中删除
smove从一个集合中向另一个集合移动元素 必须是同一类型
srem从集合中删除一个元素
sismember判断集合中是否含有这个元素
srandmember随机返回元素

5.6 ZSet类型(可根据score排序不可重复)常用命令

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

5.7 hash类型(key无序)常用命令

命令说明
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进行加法运算

6、持久化机制

redis数据保存在内存中,需要持久化机制,将数据存储到磁盘

6.1快照RDB方式(默认)

说明:这种方式可以将某一时刻的所有数据都写入硬盘中,保存的文件是以.rdb形式结尾的文件
在redis.conf文件中可根据 dbfilename dump.rdb 和 dir ./修改文件名和保存位置

a.客户端方式:

BGSAVE指令触发持久化:

redis接收到BGSAVE命令,会调用fork创建一个子进程(几乎和主进程一样,且共享资源),子进程负责将快照写入磁盘中,而父进程则继续处理命令请求

SAVE指令触发持久化:

redis主进程阻塞,接收到SAVE命令在快照创建完毕之前将不再响应任何其他的命令

shutdown指令触发持久化:

redis通过shutdown指令接收到关闭服务器的请求时,会执行一个save命令,阻塞所有的客户端,不再执行命令,save命令执行完毕后关闭服务器

b.服务器配置自动触发:

在redis.conf中设置多个save配置选项,当任意一个save配置选项条件满足,redis会触发一次BGSAVE命令,例:save 300 100:当300s内有100个key值变化则保存

6.2 AOF持久化

说明:AOF持久化会将执行的写命令写到AOF的文件末尾,记录数据发生的变化,下次只要redis执行一次AOF文件所包含的所有写命令,就可以恢复AOF文件的记录的数据集.

开启AOF持久化(redis.conf配置):
- a.修改 appendonly yes 开启持久化
- b.修改 appendfilename "appendonly.aof" 指定生成文件名称
- c.修改appendfsync everysec(推荐) 修改日志同步频率

解释日志同步频率:
	eversec:每秒执行一次同步显式的将多个写命令同步到磁盘(即使系统崩溃,最多丢失一秒的数据)
	always:个redis写命令都要同步写入硬盘,严重降低redis速度,降低硬盘使用寿命
	no:由操作系统决定何时同步,当系统崩溃时,会丢失不定数量的数据;当硬盘读写效率低,缓冲区需等待,redis阻塞,导致处理请求速度下降
AOF重写(ReWriter)机制

说明:AOF持久化问题:若对一个key改变100次数据,则文件保存100条命令,文件利用率极低,使用AOF重写,可以只保存一条命令,压缩文件大小

触发重写方式:

# 1.客户端方式触发重写
- 执行BGREWRITEAOF命令  不会阻塞redis的服务

# 2.服务器配置方式自动触发(redis.conf配置)
- auto-aof-rewrite-percentage 100
- auto-aof-rewrite-min-size 64mb

解释:
auto-aof-rewrite-min-size: 表示运行AOF重写时文件最小体积, 默认为64MB;
Redis在最近一次重写后记住AOF文件的大小(默认:启动时AOF的大小)。当AOF日志大小增加100%时,则触发重写,隐式调用BGREWRITEAOF。

重写原理:

- 1.redis调用fork创建一个子进程(几乎和主进程一样,且共享资源) 
- 2.子进程根据内存中的数据库状态快照,往临时文件写入重建数据库状态的命令
- 3. 父进程继续处理client请求,把写命令写入到原来的aof文件中,并把写命令缓存,保证若子进程重写失败不会出问题。
- 4. 子进程把快照内容写到临时文件中后,发信号通知父进程,父进程把缓存的写命令写入到临时文件。
- 5. 父进程可以使用临时文件替换老的aof文件,并重命名,后面收到的写命令开始往新的aof文件中追加。

7、java操作Redis

a.引入依赖
<!--引入jedis连接依赖-->
<dependency>
	<groupId>redis.clients</groupId>
	<artifactId>jedis</artifactId>
	<version>2.9.0</version>
</dependency>
b.第一个程序
public class TestClient {
   public static void main(String[] args){
       //1.创建jedis对象(redis服务必须关闭防火墙,开启远程连接)
       Jedis jedis = new Jedis("192.168.136.138", 6379);
       //2.执行相关操作(使用jedis对象操作redis)
       jedis.select(0);
       jedis.append("message","消息");
       //3.释放资源
       jedis.close();
   }
}

8、SpringBoot整合Redis

引言:

由于jedis方法只收字符串,传对象较繁琐,需要引入fastjson使用JSONObject将对象转为json字符串存到redis中。所以需要Spring Boot Data(数据) Redis 中提供的RedisTemplate和StringRedisTemplate

介绍:

StringRedisTemplate是RedisTemplate的子类,方法基本一致,不同之处主要体现在操作的数据类型不同,前者操作String类型,后者操作Object类型。

使用:

a.引入依赖

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

b.配置application.propertie

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

c.使用StringRedisTemplate操作string类型示例

@SpringBootTest
class SpringbootRedisApplicationTests {
   @Autowired
   private StringRedisTemplate StringredisTemplate;
   @Test
   public void testKeys(){
   	   //操作key
       Set<String> keys = StringredisTemplate.keys("*");
       keys.forEach(key-> System.out.println(key));
   }
   @Test
   public void testString(){
       //spring data redis API:提供了 OpsForxxx()方法,指定key的类型,字符串类型特殊(opsForValue)
       ValueOperations<String, String> stringOperations = StringredisTemplate.opsForValue();
       //添加一个key-value-存活时间-单位
       stringOperations.set("name","zhangsan",1L, TimeUnit.DAYS);
       //用opsForValue()获取的对象操作string类型......
   }
}

d.使用RedisTemplate操作操作string类型示例

@SpringBootTest
public class TestRedisTemplate {
   //redisTemplate操作时,会将key和value都进行序列化(转为二进制数据,能够在网络上传输或将对象保存到文件中)
   @Autowired
   private RedisTemplate<Object,Object> redisTemplate;
   @Test
   public void testKey(){
       //阻止key的序列化,否则keys(*) ——> keys(xxx),取不到值
       redisTemplate.setKeySerializer(new StringRedisSerializer());
       Set<Object> keys = redisTemplate.keys("*");
       keys.forEach(System.out::println);
   }
   @Test
   public void testString(){
       //注意:某个对象要序列化,需要实现接口
       //     string类型已经实现了序列化接口,所有student会变成xxxx...,再想要拿此数据比较困难,应取消String的序列化
       redisTemplate.setKeySerializer(new StringRedisSerializer());
       ValueOperations<Object, Object> valueOperations = redisTemplate.opsForValue();
       valueOperations.set("student",new Student(1,"zhangsan",20));
       //student会进行反序列化(二进制——>java对象)
       Student student = (Student) valueOperations.get("student");
       System.out.println(student);
   }

e.RedisTemplate和StringRedisTemplate的bond绑定

@SpringBootTest
public class TestBound {
   //1.opsForxxx
   //2.bound绑定 : boundXxxOps() 用来对一个key进行多次操作推荐使用该类型方法
   @Autowired
   private StringRedisTemplate stringRedisTemplate;
   @Test
   public void testString(){
       ValueOperations valueOperations = stringRedisTemplate.opsForValue();
       valueOperations.set("name","zhangsan");
       valueOperations.append("name","haha");

       //绑定age这个key,直接使用
       BoundValueOperations<String, String> age = stringRedisTemplate.boundValueOps("age");
       age.set("20");
   }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值