Redis
- 前言
- Redis
- Redis的安装
- Redis启动
- Redis客户端
- Redis常见命令
- Redis的java客户端
- jedis学习
- 简单的jedis 入门流程
- Jedis连接池
- SpringDataRedis
- SpringDataRedis快速入门
前言
我们在作者之前的文章: 快速掌握Redis安装与基本语法的基础上进行系统的学习,学习自黑马程序员的Redis实战课堂,进行学习总结,希望对大家有所帮助
Redis
SQL语句与NoSQL语句的特点:
数据关联
:在关系型数据库中,表与表之间存在数据库的关联信息,而NoSQL
数据之间没有关联信息,需要自定义逻辑进行信息关联
事务特性
: NoSQL只能维持基本的事务操作,所以一般对事务性要求高的需要用关系型数据库
数据结构
:不是说完全自由,有一个宽泛的整体结构,比如Redis
为键值类型
,MongDB
为文档类型
,列类型(HBse)
,Graph(Neo4j)
扩展性
: 垂直就是数据库需要部署在一个机器上,只能够通过添加存储空间的方式进行优化,而水平
就是Redis存储数据时根据id
值通过hash进行运算分布式的存储在多个机器上
单线程
:每个命令具有原子性,现在常说的版本是多线程是指在网络请求方面是多线程处理,其本质还是单线程
低延迟,速度快
:基于内存,IO多路复用
数据持久化
:定时将内存数据写入到磁盘当中
支持主从集群,分片集群
:提高上述所讲的水平扩展
Redis的安装
前边所讲的Redis的安装,安装的版本是windows版本的,我们现在安装Linux版本
安装地址:https://redis.io/
步骤:
- 执行
yum install -y gcc ctl
:安装Redis依赖,Rrdis是基于C语言开发的,需要gcc依赖 - 将下载的Redis压缩包上传到
/usr/local/src
目录下 - 进行解压
- 进入到解压后的Redis目录下执行
make && make install
:先编译后安装 - 默认的安装目录在
/usr/local/bin
目录下 - 该目录已经默认配置到环境变量,因此可以在任意目录下运行这些命令
redis-cli
:是redis提供的命令行客户端
redis-server
:是redis的服务端启动脚本
redis-sentinel
:是redis的哨兵启动脚本
Redis启动
- 启动方式
默认启动
:执行redis-server
这种属于前台启动,会阻碍整个会话窗口,如果ctrl+c退出,redis停止
后台启动:
- 修改redis的配置文件在
/usr/local/src/redis-7
目录下的redis.conf
cp redis.conf redis.conf.bck
:先备份一份文件- 修改监听的地址
bind 监听地址
,学习可以设置为 0.0.0.0允许任意网络访问 - 修改守护进程为
daemonize yes
:可以进行后台运行 - 设置密码
requirepass 密码
- 回到解压目录下再次启动redis执行
redis-server redis.conf
Redis开机自启动
- 执行
vi /etc/systemd/system/redis.service
:创建一个系统服务文件 - 在文件中输入:
[Unit]
Description=redis-server
After=network.target
[Service]
Type=forking
ExecStart=/usr/local/bin/redis-server /usr/local/src/redis-7.0.15/redis.conf
[Install]
WantedBy=multi-user.target
- 重载系统服务
systemctl daemon-reload
- 启动服务
systemctl start redis
- 设置开机自启动
systemctl enable redis
Redis其他常用配置
7. port 端口号
:设置监听的端口号
8. dir .
:工作目录(默认当前目录),保存运行的日志文件,持久化等文件
9. database 数量
:设置数据库的数量,表示能使用几个库默认16个
10. maxmemory 512mb
:设置redis能够使用的最大内存
11. logfile "redis.log"
:指定日志文件名称
Redis客户端
命令行客户端:
Redis安装之后就自带命令行客户端redis-cli
redis-cli [选项] [命令]
选项:
-h 127.0.0.1
:指定要连接的redis节点的ip地址,默认为127.0.0.1
-p 6379
:指定要连接的redis节点的端口,默认为6379
-a 123456
:指定访问redis的访问密码
命令:
指连接上redis之后要进行的操作,例如:
ping
:从客户端向服务器段进行连接测试,正常返回pong
不指定命令连接redis客户端会进入redis-cli
的交互控制台
图形化客户端:
安装地址:https://github.com/lework/RedisDesktopManager-Windows/releases
解压后双击进行安装:
安装之后双击resp.exe
文件启动
进入连接设置:
创建连接,成功后:
Redis常见命令
在学习Redis的常用命令少不了帮助文档:https://redis.io/commands
我们也可以在客户端命令行中通过help
进行相关查看
Redis数据库中Key一般是String类型,value类型:
list
:一个有序的集合,本质是一个链表
Set
:无序集合
SortedSet
:可排序的集合
GEO
:一个地理坐标
BitMap和HyperLog
:特殊的按照位进行存储,本质是字符串
在进行命令的学习中建议配合help
命令进行学习
- Redis通用命令
KEYS [模板]
:查询符合模板所有的key,例如keys *name*
:匹配所有中间由name的key
DEL
:删除一个指定的key,也可以删除多个key,多个key用空格隔开
EXISTS
:判断key是否存在例如exists age
EXPIRE
:给一个key设置有效期,有效期到期会自动删除key例如repire age 20
设置有效期为20秒
TTL
: 查看一个key的剩余有效期
- String类型的数据
存储的数据可能是字符串类型,也可能字符串是数字或浮点数,不管是哪种格式,底层都是字节数组存储,数字类型的字符串编译成二进制文件存储在字节数组中,而字符串是以字母的形式存入字节数组的
String常见的命令
incrby age -1
:控制key进行自减
setex age 20
:添加一个key并设置有效期
注意:在开发过程中我们都通过id作为key进行存储,如果我们的用户id为1,商品信息的id也为1,那么这个时候我们应该如何进行区分呢:
Redis的key允许有多个单词形成层级结构,多个单词之间用:
隔开
项目名:业务名:类型名:id
如果value是一个java对象:将对象序列化为JSON字符串后存储
- Hash类型数据
Hash类型,也叫散列,其value是一个无序字典,类似于java中的HashMap结构
在Spring类型中java对象是序列化为JSON格式的字符串进行存储,但是这样能进行修改
Hash结构可以将对象中的每个字段进行独立存储,方便修改:
Hash类型常见命令
- List类型
Redis中的list类型与java中的LinkedList类似,可以看作一个双向链表结构,可以进行正向检索,也可以进行反向检索
特征:有序,元素可以重复,插入和删除快,查询速度一般
List的常见命令
- Set类型
Redis的Set结构与java中的HashSet类型,可以看作是一个value为null的HashMap
特征:无序,元素不可重复,查找块,支持交集并集差集
Set常用命令
- SortedSet类型
Redis的SortedSet是一个可排序的set集合,与java中的treeSet有些相似,但底层数据结构差距很大,SortSet中的每一个元素都带有一个score属性,可以基于score属性对元素进行排序,底层实现一个跳表(SkipList) {实现排序,加快查询速度}加Hash表
特征:可排序,元素不重复,查询速度块
实际应用:用来实现排行榜这样的功能
SortedSet常用指令
注意:所有的排序默认都是升序的,如果要降序则在命令的Z之后添加REV即可
场景应用:将班级的学生和成绩存入redis并进行排名
Redis的java客户端
在Redis官网中提供了各种语言的客户端
地址:https://redis.io/clients
客户端 | 简介 |
---|---|
jedis | 以Redis命令作为方法名称,简单实用易学习,但是jedis实例是线程不安全的,多线程环境下需要基于连接池使用 |
lettuce | 是基于Netty实现的,支持同步,异步和响应式编程方式,线程安全,支持Redis哨兵模式,集群模式和管道模式 |
Redisson | Redisson是一个基于Redis实现的分布式,可伸缩的java数据结构集合,包含了Map,Queue,Lock等强大功能 |
Spring Data Redis | Spring框架给出的整合jedis和lettuce的技术 |
jedis学习
jedis官方地址:http://github.com/redis/jedis
简单的jedis 入门流程
第一步:导入依赖
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>5.0.2</version>
</dependency>
第二步: 建立连接
private Jedis jedis
//给出jedis的初始化方案
@BeforeEach
void setUp(){
jedis =new Jedis("虚拟机的ip",redis端口号);
jedis.auth("密码");
//选择库
jedis.select(0);
}
第三步:通过jedis进行操作,例如
String result=jedis.set("name","wode")
String name=jedis.get("name")
第四步:释放资源
jedis.close()
Jedis连接池
创建jedis连接池:
public class JedisConnectionFactory {
private static final JedisPool jedispool;
static {
//通过连接池配置对象配置连接池
JedisPoolConfig jedisPoolConfig=new JedisPoolConfig();
//设置最大连接数
jedisPoolConfig.setMaxTotal(8);
//设置最大空闲连接
jedisPoolConfig.setMaxIdle(8);
//设置最小空闲连接,当很长一段时间没有使用连接,连接就会被销毁
jedisPoolConfig.setMinIdle(0);
//设置当连接池中没有连接的时候等待的最大时间
jedisPoolConfig.setMaxWaitMillis(1000);
jedispool=new JedisPool(jedisPoolConfig,"虚拟机ip",6379,1000,"密码");
}
public static Jedis getJedis(){
return jedispool.getResource();
}
}
创建Jedis连接池后再进行创建jedis的时候就从连接池获取连接
Jedis jedis=JedisConnectionFactory.getJedis();
同时释放资源的时候就成为还回连接
SpringDataRedis
SpringData是Spring中数据操作的整合,其中对Redis的集成模块就叫做SpringDataRedis
官网地址:https://spring.io/projects/spring-data-redis
SpringDataRedis简述
- 提供了Redis客户端整合(lettuce和Jedis)
- 提供了RedisTemplate来统一API来操作Redis
- 支持Redis的发布订阅模型
- 支持Redis哨兵和Redis集群
- 支持基于Lettuce的响应式编程
- 支持基于JDK,JSON,字符串,SPring对象的数据序列化及反序列化
- 支持基于Redis的JDKCollection实现
SpringDataRedis中提供了RedisTemplate工具类,封装了各种对Redis的操作,并且将不同的数据类型的操作API封装:
SpringDataRedis快速入门
第一步:引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
连接池的依赖
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
第二步:配置文件信息
spring:
data:
redis:
host: 192.168.75.134
port: 6379
password: 520521
lettuce:
pool:
max-active: 8 #最大连接
max-idle: 8 #最大空闲数
min-idle: 0 # 最小空闲连接
max-wait: 100 #连接等待时间
注意:在配置文件中默认使用的是lettuce的pool连接池,这是Spring默认的,如果使用jedis的pool还需引入jedis的依赖
第三步:注入RedisTemplate
@Autowired
private RedisTemplate redistemplate;
第四步:进行操作
redistemplate.opsForValue().set("name","wode")
:插入一条String类型的数据
Object name=redistemplate.opsForValue().get("name")
:读取一条String类型数据
注意:在执行第四步的插入操作之后,在redis中出现一条长文
这是由于在redistemplate中都是以对象的形式进行输入的,在输入之后,通过SpringDataRedis中的JDK序列化将java对象转化为字节的方式传输到redis中
这样肯定是不方便的,那么怎么办,需要写出自己的序列化方式
- 自定义序列化方式
@Configuration
public class Redisconfig {
@Bean
public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory connectionFactory){
//创建RedisTemplate对象
RedisTemplate<String, Object> stringObjectRedisTemplate = new RedisTemplate<>();
//设置连接工厂
stringObjectRedisTemplate.setConnectionFactory(connectionFactory);
//创建JSON序列化工具
GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
//设置key的序列化
stringObjectRedisTemplate.setKeySerializer(RedisSerializer.string());
stringObjectRedisTemplate.setValueSerializer(genericJackson2JsonRedisSerializer);
stringObjectRedisTemplate.setHashValueSerializer(genericJackson2JsonRedisSerializer);
//设置value的序列化
//返回
return stringObjectRedisTemplate;
}
}
这样就会解决了序列化的问题,但是你会发现使用JSON的序列化器后,在redis的数据中会出现反序列化所需要的类名,一旦数据多了,每条数据有一条类信息,这就会非常的臃肿,耗费内存
为了节省空间,我们不采用JSON的序列化器来处理value,而是统一使用String序列化器,要求只能存储string类型的key和value,所以,当需要存储java对象的时候,手动完成对象的序列化和反序列化
这时Spring提供了一个StringRedisTemplate类,它的key和value的序列化方式就是String方式,大大方便我们
private StringRedisTemplate stringredistemplate;
//通过这个类再执行相应的redis操作的时候默认的序列化方式就是string
只不过需要将对象进行手动的序列化
private static final ObjectMapper mapper=new ObjectMapper();
//创建对象
User user=new User("nihao",2);
//手动的序列化
String json=mapper.writeValueAsString(user);
StringRedisTemplate.opsForValue().set("User:1",user);