NOSQL——Redis详细讲解

简介

NOSQL(No Only SQL)仅仅是一个概念,泛指非关系型的数据库,区别于关系数据库,它们不保证关系数据的ACID特性。

NOSQL的四大类型

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

  • 相关产品:Redis、Riak、SimpleDB、Chordless、Scalaris、Memcached

  • 应用:内容缓存,处理大量数据的高负载访问,也用于系统日志

  • 优点:扩展性好、灵活性好、大量写操作时性能高

  • 缺点:无法存储结构化信息、条件查询效率较低

  • 使用者:百度云(Redis)、GitHub(Riak)、BestBuy(Riak)、Twitter(Ridis和Memcached)

  1. 列存储数据库

  • 相关产品:BigTable、HBase、Cassandra、HadoopDB、GreenPlum、PNUTS

  • 应用:分布式数据存储与管理

  • 优点:查找速度快、可扩展性强、容易进行分布式扩展、复杂性低

  • 缺点:写入次数多,速度慢,消耗cpu

  • 使用者:Ebay(Cassandra)、Instagram(Cassandra)、NASA(Cassandra)、Facebook(HBase)

  1. 文档型数据库

  • 相关产品:MongoDB、CouchDB、ThruDB、CloudKit、Perservere、Jackrabbit

  • 应用:存储、索引并管理面向文档的数据或者类似的半结构化数据

  • 优点:性能好、灵活性高、复杂性低、数据结构灵活

  • 缺点:缺乏统一的查询语言

  • 使用者:百度云数据库(MongoDB)、SAP(MongoDB)

  1. 图形(Graph)数据库

  • 相关产品:Neo4J、OrientDB、InfoGrid、GraphDB

  • 应用:大量复杂、互连接、低结构化的图结构场合,如社交网络、推荐系统等

  • 优点:灵活性高、支持复杂的图形算法、可用于构建复杂的关系图谱

  • 缺点:复杂性高、只能支持一定的数据规模

  • 使用者:Adobe(Neo4J)、Cisco(Neo4J)、T-Mobile(Neo4J)

  1. 不同分类特点对比

分类

Examples举例

典型应用场景

数据模型

优点

缺点

键值(key-value)

Tokyo Cabinet/Tyrant, Redis, Voldemort, Oracle BDB

内容缓存,主要用于处理大量数据的高访问负载,也用于一些日志系统等等。

Key 指向 Value 的键值对,通常用hash table来实现

查找速度快

数据无结构化,通常只被当作字符串或者二进制数据

列存储数据库

Cassandra, HBase, Riak

分布式的文件系统

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

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

功能相对局限

文档型数据库

CouchDB, MongoDb

Web应用(与Key-Value类似,Value是结构化的,不同的是数据库能够了解Value的内容)

Key-Value对应的键值对,Value为结构化数据

数据结构要求不严格,表结构可变,不需要像关系型数据库一样需要预先定义表结构

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

图形(Graph)数据库

Neo4J, InfoGrid, Infinite Graph

社交网络,推荐系统等。专注于构建关系图谱

图结构

利用图结构相关算法。比如最短路径寻址,N度关系查找等

很多时候需要对整个图做计算才能得出需要的信息,而且这种结构不太好做分布式的集群方案。

优点:扩展,NoSQL数据库种类繁多,但是一个共同的特点都是去掉关系数据库的关系型特性。数据之间无关系,这样就非常容易扩展。无形之间也在架构的层面上带来了可扩展的能力。(数据类型多样,不需要事先设计数据库)大数据量高性能,NoSQL数据库都具有非常高的读写性能,尤其在大数据量下,同样表现优秀。这得益于它的无关系性,数据库的结构简单。

Redis

Redis,英文全称是Remote Dictionary Server(远程字典服务),是一个开源的使用ANSI C语言编写支持网络可基于内存亦可持久化的日志型Key-Value数据库并提供多种语言的API

MySQL数据库不同的是,Redis的数据是存在内存中的。它的读写速度非常快,每秒可以处理超过10万次读写操作。因此redis被广泛应用于缓存,另外,Redis也经常用来做分布式锁。除此之外,Redis支持事务持久化(RDB,AOF)LUA 脚本LRU 驱动事件多种集群方案(主从集群,分片集群)

安装Redis

linux服务器部署Redis (linux版本 CentOS 7)

  1. Reids是基于C语言编写的,因此需要安装redis的依赖gcc

yum install -y gcc tcl
  1. 下载Redis

redis官网: https://redis.io/download
版本: https://download.redis.io/releases/
  1. 上传安装包并解压

现在大多数Linux服务器都带有lrzsz程序,方便上传下载文件,如果没有,可以直接下载rpm包安装下就好。
lrzsz安装包链接: http://down.51cto.com/data/2322755
1、rz(笔记本上传给服务器)

rz

选择笔记本上文件传给服务器

2、sz(服务器上的文件拷贝给笔记本)

sz test.tar

把服务器的test.tar拷贝给笔记本

如下图,输入 rpm -qa |grep sz 和 rpm -qa |grep rz 命令查看是否安装该程序。

如果没有安装,可以输入 yum -install sz yum -install rz命令进行安装

把安装包上传到linux

输入 命令 rz ,如下图所示弹出一个文本框,选择要上传的文件上传即可

一般情况下,把安装包上传到 usr/local/src路径下.

解压安装包

tar -zxvf  redis-7.0.9.tar.gz

解压成功后

  1. 运行编译命令,默认安装在/usr/local/bin目录下

进入到 cd ./redis-7.0.9目录下运行编译命令

make && make install

安装成功后

  • redis-cli:redis提供的命令行客户端

  • redis-server:redis的服务端启动脚本

  • redis-sentinel:redis的哨兵启动脚本

  • reis-benchmark: redis的性能测试

性能测试语法:

redis-benchmark [参数] [参数值]                                             
-h    指定服务器主机名                                默认值为 127.0.0.1
-p    指定服务器端口                                  默认值为   6379
-s    指定服务器socket    
-c    指定并发连接数                                  默认值为   50
-n    指定请求数                                      默认值为   10000
-d    以字节的形式指定 SET/GET 值的数据大小              默认值为  2
-k    1=keep alive 0=reconnect                       默认值为  1
-r    SET/GET/INCR 使用随机 key, SADD 使用随机值    
-P    通过管道传输 请求                                 默认值为  1
-q    强制退出 redis。仅显示 query/sec 值    
–csv    以 CSV 格式输出    
-l    生成循环,永久执行测试    
-t    仅运行以逗号分隔的测试命令列表。    
-I    Idle 模式。仅打开 N 个 idle 连接并等待。
  1. 默认启动(前台启动)redis

在任意目录输入redis-server命令即可启动Redis:

这种启动属于前台启动,会阻塞整个会话窗口,窗口关闭或者按下CTRL + C则Redis停止。不推荐使用

  1. Redis后台启动需要修改 安装包usr/local/src/redis-7.0.9下的redis.conf配置文件

防止修改配置文件时出错,建议先进行备份
文件备份: cp redis.conf redis.conf.bck

修改配置文件

允许访问的地址  bind 127.0.0.1 -::1 这个地址只能在本地访问,设置为0.0.0.0可以在任意IP访问,生产地址不要这样设置
bind 0.0.0.0
# 守护进程,修改为yes后即可后台运行
daemonize yes
# 密码,设置后访问Redis必须输入密码    我这里密码设置为redis
requirepass redis
。。。。。。。。。。。。。。。。。。。下面的也可以不修改。。。。。。。。。。。。。。
# 监听的端口
port 6379
# 工作目录,默认是当前目录,也就是运行redis-server时的命令,日志、持久化等文件会保存在这个目录
dir .
# 数据库数量,设置为1,代表只使用1个库,默认有16个库,编号0~15
databases 1
# 设置redis能够使用的最大内存
maxmemory 512mb
# 日志文件,默认为空,不记录日志,可以指定日志文件名
logfile "redis.log"
        第16和10配合使用更方便查询日志

修改完之后启动配置文件

在安装包下启动 
redis-server redis.conf

可以利用进程查看Redis是否启动

关闭进程

kill -9 7362
  1. Redis还可以做到开机自启

  1. 创建一个配置文件

vi /etc/systemd/system/redis.service
  1. 把下面的内容复制进去

[Unit]
Description=redis-server
After=network.target

[Service]
Type=forking
ExecStart=/usr/local/bin/redis-server /usr/local/src/redis-7.0.9/redis.conf
PrivateTmp=true

[Install]
WantedBy=multi-user.target
  1. 配置好之后,重载系统服务,这部操作,只是把redis交给系统管理了,还没有开机自启

systemctl daemon-reload
  1. Redis自启需要一下几个命令

启动Redis
systemctl start redis
停止redis
systemctl stop redis
开机自启命令
systemctl enable redis
重新启动redis
systemctl restart redis 
查看redis状态
systemctl status redis

查看进程,自启已经开始

Redis客户端

安装完之后,操作redis需要用redis客户端,包括

  • 命令行客户端

  • 图形化界面客户端

  • 编程客户端

  1. 命令行客户端 redis-cli:

redis安装完成之后就包含了命令行客户端 : redis-cli

语法格式

redis-cli [options] [commonds] 

常见的options有:

-h 127.0.0.1

指定要连接的redis节点的IP地址 默认为127.0.0.1

-p 6379

指定要连接的redis节点端口 默认为6379

-a redis

指定访问的redis密码

其中commonds就是redis的操作命令,例如:

ping

与redis服务端做心跳测试

不指定commonds时,会进入redis-cli的交互控制台

连接redis

连接redis时,使用127.0.0.1和IP地址都可以,如下图所示

上面的警告信息是提示-a这种方式指定密码不安全,所以我们用Auth命令指定用户名和密码

  1. 图形化界面客户端

图形化界面客户端不是官方提供,是Github编写的redis的图形化界面客户端,地址:GitHub - RedisInsight/RedisDesktopManager,不过该仓库提供了RedisDesktopManager的源码,没有提供windows安装包

安装包地址:Releases · lework/RedisDesktopManager-Windows (github.com)

下载解压后如图所示

运行.exe文件进行安装,傻瓜式安装

连接redis服务器

连接成功可以在界面上操作redis,建议初学者,使用命令行操作redis

Redis数据结构

redis是一个key-value数据库,key一般是String类型,

value类型多种多样 ,例如:

(String,hash,set,list,sortedset,GEO,bitMap,HyperLog)

  1. Redis通用命令

通过 help[command] 可以查看一个命令的基本用法

  • keys 查看所有符合的key值 ,因为是模糊查询性能差,不建议在生产环境使用

例:

  • DEL 删除指定的key

例:

  • Exists 判断key是否存在

  • EXPIRE 给一个key设置有效期,有效期到期时该key会被自动删除

  • TTL 查看key的剩余有效时间

  1. Redis的String类型

String类型 Redis中最简单的存储类型。value是字符串。

value是字符串,根据字符串的类型不同又可以分为三类

  • String 普通字符串

  • int 整数类型 可以做自增、自减操作

  • float 浮点类型,可以做自增、自减操作

不管那种类型,底层都是字节数组形式存储,只不过编码方式不同,字符串类型最大空间不超过512M

String类型的常见命令

    SET:添加或者修改已经存在的一个
    String类型的键值对
    GET:根据key获取
    String类型的value
    MSET:批量添加多个String类型的键值对
    MGET:根据多个key获取多个String类型的value
    INCR:让一个整型的key自增1
    INCRBY:让一个整型的key自增并指定步长,例如:incrby num 2 让num值自增2
    INCRBYFLOAT:让一个浮点类型的数字自增并指定步长
    SETNX:添加一个String类型的键值对,前提是这个key不存在,否则不执行
    SETEX:添加一个String类型的键值对,并且指定有效期

Redis的key允许有多个单词形成层级结构,多个单词之间用“:”隔开 格式如下图所示

  1. Redis的Hash类型

Hash类型,也叫散列,其value是一个无序字典,类似于Java中的HashMap结构。

String结构是将对象序列化为JSON字符串后存储,当需要修改对象某个字段时很不方便

Hash结构可以将对象中的每个字段独立存储,可以针对单个字段做CRUD

 HSET key field value:添加或者修改hash类型key的field的值
 HGET key field:获取一个hash类型key的field的值
 HMSET:批量添加多个hash类型key的field的值
 HMGET:批量获取多个hash类型key的field的值
 HGETALL:获取一个hash类型的key中的所有的field和value
 HKEYS:获取一个hash类型的key中的所有的field
 HVALS:获取一个hash类型的key中的所有的value
 HINCRBY:让一个hash类型key的字段值自增并指定步长
 HSETNX:添加一个hash类型的key的field值,前提是这个field不存在,否则不执行

示例:

  1. Redis的List类型

Redis中的List类型与Java中的LinkedList类似,可以看做是一个双向链表结构,既可以支持正向检索,也支持反向检索。常用来存储一些有序数据

特点:

  • 有序

  • 元素可以重复

  • 插入和删除快,查询慢

List常见命令:

 LPUSH key  element ... :向列表左侧插入一个或多个元素
 LPOP key:移除并返回列表左侧的第一个元素,没有则返回nil
 RPUSH key  element ... :向列表右侧插入一个或多个元素
 RPOP key:移除并返回列表右侧的第一个元素
 LRANGE key star end:返回一段角标范围内的所有元素
 BLPOP和BRPOP:与LPOP和RPOP类似,只不过在没有元素时等待指定时间,而不是直接返回nil
  • 如何利用List结构模拟一个?

  • 入口和出口在同一边

  • 如何利用List结构模拟一个队列?

  • 入口和出口在不同边

  • 如何利用List结构模拟一个阻塞队列?

  • 入口和出口在不同边

  • 出队时采用BLPOP或BRPOP

  1. Redis的set类型

Redis的Set结构与Java中的HashSet类似,可以看做是一个value为null的HashMap。

因为也是一个hash表,因此具备与HashSet类似的特征:

  • 无序

  • 元素不可重复

  • 查找快

  • 支持交集、并集、差集等功能

Set常见命令:

 SADD key member ... :向set中添加一个或多个元素
 SREM key member ... : 移除set中的指定元素
 SCARD key: 返回set中元素的个数
 SISMEMBER key member:判断一个元素是否存在于set中
 SMEMBERS:获取set中的所有元素
 SINTER key1 key2 ... :求key1与key2的交集
 SDIFF key1 key2 ... :求key1与key2的差集
 SUNION key1 key2 ..:求key1和key2的并集
  1. Redis的SortedSet类型:

Redis的SortedSet是一个可排序的set集合,与Java中的TreeSet有些类似,但底层数据结构却差别很大。

SortedSet中的每一个元素都带有一个score属性,可以基于score属性对元素排序,底层的实现是一个跳表(SkipList)加 hash表

SortedSet具备下列特性:

  • 可排序

  • 元素不重复

  • 查询速度快

因为SortedSet的可排序特性,经常被用来实现排行榜这样的功能。

 ZADD key score member:添加一个或多个元素到sorted set ,如果已经存在则更新其score值
 ZREM key member:删除sorted set中的一个指定元素
 ZSCORE key member : 获取sorted set中的指定元素的score值
 ZRANK key member:获取sorted set 中的指定元素的排名
 ZCARD key:获取sorted set中的元素个数
 ZCOUNT key min max:统计score值在给定范围内的所有元素的个数
 ZINCRBY key increment member:让sorted set中的指定元素自增,步长为指定的increment值
 ZRANGE key min max:按照score排序后,获取指定排名范围内的元素
 ZRANGEBYSCORE key min max:按照score排序后,获取指定score范围内的元素
 ZDIFF、ZINTER、ZUNION:求差集、交集、并集

注意:所有的排名默认都是升序,如果要降序则在命令的Z后面添加REV即可

Redis的JAVA客户端

搭建redis-java项目

  1. Jedis

  1. Jedis快速入门
  1. 导入依赖
<dependency>
     <groupId>redis.clients</groupId>
     <artifactId>jedis</artifactId>
     <version>4.3.2</version>
</dependency>
  1. 编写测试类
package com.test.jedis;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import redis.clients.jedis.Jedis;

import java.util.List;


/**
 * @author 
 * @version 1.0
 * @description: TODO
 * @date 2023/4/25 16:41
 */
public class ProjectTest {

    private Jedis jedis;

    @Before
    public void connectRedis(){
        //连接redis
        jedis=new Jedis("192.168.9.128",6379);
        //输入redis密码
        jedis.auth("redis");
        //设置redis数据库
        jedis.select(0);
    }

    @Test
    public void RedisTest(){
        //存储数据
        jedis.set("name","张三");
        jedis.mset("age", "12","sex","男");
        List<String> mget = jedis.mget("name", "age", "sex");
        //获取数据
        System.out.println(mget.toString());
    }

    @After
    public void stopRedis(){
        //关闭连接
        if(jedis!=null){
            jedis.close();
        }
    }
}
@Before注释函数将在具有@Test注释的类中的每个测试函数之前执行 =用法= @beforeEach
@After注释函数将在类中具有@Test批注的每个测试函数之后执行 =用法= aftereach
  1. 测试结果
  1. Jedis连接池

Jedis本身是线程不安全的,并且频繁的创建和销毁连接会有性能损耗,因此推荐使用Jedis连接池代替Jedis的直连方式

连接池配置 (也可以在yml文件中配置 利用@Value获取)

package com.redis.test.util;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

/**
 * @author
 * @version 1.0
 * @description: TODO
 * @date 2023/4/26 11:20
 */
public class RedisConnectionFactory {

    private static final JedisPool jedisPool;

    static {
        //连接池配置
        JedisPoolConfig config = new JedisPoolConfig();
        //创建连接池最大连接数
        config.setMaxTotal(8);
        //设置最大空闲连接
        config.setMaxIdle(8);
        //设置最小空闲连接      空闲连接一直空着占用内存,所以超过一段时间以后一直没有连接,空闲连接就会被释放
        config.setMinIdle(0);
        //设置连接等待时长 毫秒      连接池没有可用的空闲连接时,最多等待多长时间 默认值为 -1  无限制等待,直到有连接池可用
        config.setMaxWaitMillis(1000);

        //minEvictableIdleTimeMillis  连接池中连接,在时间段内一直空闲, 被逐出连接池的时间
        config.setMinEvictableIdleTimeMillis(2000);

        //配置连接池对象  ms
        jedisPool=new JedisPool(config,"192.168.9.128",6379,1000,"redis");
    }

    public static Jedis getJedis(){
        return jedisPool.getResource();
    }
}

快速入门里测试类的连接方式修改一下

这里测试时有一个问题,

Jedis测试时,因为我用的版本是<version>4.3.2</version>,报如下错误

加上setMinEvictableIdleTimeMillis参数还是不行,最后换了一个版本<version>3.3.0</version>测试成功。

还有一个需要注意一下:

在关闭连接时,如果有连接池,close()方法是归还到连接池中而不是销毁

源码如下:

  1. SpringDataRedis

SpringData是Spring中数据操作的模块,包含对各种数据库的集成,其中对Redis的集成模块就叫做SpringDataredis

官网地址:http://spring.io/projects/spring-data-redis

  • 提供了对不同Redis客户端的整合(Lettuce和Jedis)

  • 提供了Redistemplate统一API来操作Redis

  • 支持Redis的发布订阅模型

  • 支持Redis哨兵和Redis集群

  • 支持基于Lettuce的响应式编程

  • 支持基于JDK、JSON、字符串、Spring对象的数据序列化及反序列化

  • 支持基于Redis的JDKCollection实现

SpringDataRedis中提供了RedisTemplate工具类,其中封装了各中对Redis的操作。并且将不同数据类型的操作API封装到了不同的类型中:

  1. 导入依赖:
 <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>
  1. 编写yml文件
spring:
  redis:
    host: 192.168.9.128
    port: 6379
    password: redis
    lettuce:
      pool:
        max-active: 8
        max-idle: 8
        min-idle: 0
        max-wait: 1000ms
  1. 测试RedisTemplate连接Redis
package com.redis.test;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;


/**
 * @author 
 * @version 1.0
 * @description: TODO
 * @date 2023/4/25 16:41
 */
@SpringBootTest
public class ProjectTest {

    @Autowired
    private RedisTemplate redisTemplate;

    @Test
    public void redisConnection(){
        redisTemplate.opsForValue().set("name","历史");
        Object name = redisTemplate.opsForValue().get("name");
        System.out.println(name);
    }
}
  1. 测试结果:
  1. RedisTemplate序列化问题

使用RedisTemplate用一个问题,RedisTemplate是使用序列化写入值

方法可以存储任何类型的数据 如下

SpringDataRedis会把储存的数据转化为Redis可以处理的字节

源码如下:

RedisTemplate默认提供了四种序列化方式

如果不指定序列化方式,那么默认是采用JDK序列化

把java对象转化为字节,造成可读性差,内存占用比较大(存储的数据类似乱码的情况)

解决这种情况,需要改变redisTemplate序列化对象RedisSerializer

StringRedisSerializer序列只能处理String类型数据

GenericJackson2JsonRedisSerializer序列可以处理对象类型数据

修改Redistemplate序列后,代码如下:

package com.redis.test.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.nio.charset.Charset;

/**
 * @author 
 * @version 1.0
 * @description: TODO
 * @date 2023/4/27 17:18
 */

@Configuration
public class RedisConfig {

    //解决redisTemplate存储的数据乱码问题
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        //创建RedisTemplate对象
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        //设置连接工厂
        template.setConnectionFactory(factory);
        //设置key的序列化
        template.setKeySerializer(RedisSerializer.string());
        template.setHashKeySerializer(RedisSerializer.string());
        //设置value的序列化
        template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());

        return template;
    }
}

Redis缓存

缓存(Cache)就是数据交换的缓冲区,是存储数据的临时地方,一般读写性能较高

添加Redis缓存

原始的是,客户端发起请求访问数据库,数据库查到信息响应给客户端;

添加redis缓存后,客户端发起请求,先去redis缓存中查找数据,如果有数据,redis就返回给客户端,没有数据,客户端去数据库中查找,数据库返回给客户端,并且把数据存储到redis缓存,下次请求直接在redis缓存中获取。

示例:

待更新。。。。。。。。。。。。。。。。。。。。。。。。。。。。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值