00_Redis初识

Redis 是一个开源的使用 ANSI C 语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库。

Posted by silhouette on June 15, 2020

前言

因为手上的一个项目要用到 Redis,所以就利用空余时间来的学习一下 Redis。之前有了解过 Redis及其一些简单的使用,但是知识点太零碎了,所以打算系统的学习一下 Redis,并将学习过程记录下来,以供后期复习和巩固。废话不多说,那我们就开始吧!!!

一、Redis 初识

1.1 NoSQL 介绍

1.1.1 什么是 NoSQL

  • NoSQL(NoSQL = Not Only SQL),意即“不仅仅是SQL”,是一项全新的数据库理念,泛指非关系型的数据库
  • 随着互联网web2.0网站的兴起,传统的关系数据库在应付web2.0网站,特别是超大规模和高并发的SNS类型的web2.0纯动态网站已经显得力不从心,暴露了很多难以克服的问题,而非关系型的数据库则由于其本身的特点得到了非常迅速的发展。NoSQL数据库的产生就是为了解决大规模数据集合多重数据种类带来的挑战,尤其是大数据应用难题。
  • 目前一些主流的 NoSQL 产品有:MongoDB、CouchDB、Redis、Membase、Neo4j 、 HBase等。

1.1.2 非关系型数据库与关系型数据库的优势对比

  • 非关系型数据库的优势:

    • NoSQL 是基于键值对的,可以想象成表中的逐渐和值的对应关系,而且不需要经过 SQL层的解析,所以性能非常高
    • 可扩展性也是因为是基于键值对,数据之间没有耦合性,所以非常容易水平扩展
  • 关系型数据库的优势:

    • 复杂查询可以用 SQL 语句方便的在一个表以及多个表之间做非常复杂的数据查询
    • 实物支持是得对于安全性能很高的数据访问要求得以实现。

    Tips:NoSQL 的出现是为了解决关系型数据库中的难题,所以对方的优势就是自己的缺陷,反之亦然。

1.1.3 NoSQL 与关系型数据库优劣对比

  • 优点:
    • 成本:NoSQL 数据库简单易部署,基本都是开源软件,不需要像使用 Oracle 那样花费大量成本购买使用,相比关系型数据库价格便宜。
    • 查询速度:NoSQL 数据库将数据存储于缓存之中,关系型数据库将数据存储在硬盘中,自然查询速度远不及 NoSQL 数据库。
    • 存储数据的格式:NoSQL 的存储格式(key,value)形式、文档形式、图片形式等等,所以可以存储基础类型以及对象或者是集合等各种格式,而数据库则只支持基础类型。
    • 扩展性:关系型数据库有类似join这样的多表查询机制的限制导致扩展很艰难。
  • 缺点:
    • 维护的工具和资料有限,因为 NoSQL 是属于新的技术,不能和关系型数据库10几年的技术同日而语。
    • 不提供对 SQL 的支持,如果不支持 SQL 这样的工业标准,将产生一定用户的学习和使用成本。
    • 不提供关系型数据库对事务的处理

Tips:关系型数据库与NoSQL数据库并非对立而是互补的关系,即通常情况下使用关系型数据库,在适合使用NoSQL的时候使用NoSQL数据库,让NoSQL数据库对关系型数据库的不足进行弥补。一般会将数据存储在关系型数据库中,在 NoSQL 数据库中备份存储关系型数据库的数据

1.1.4 NoSQL 数据库分类

  • 键值(Key-Value)存储数据库
    • 相关产品: Tokyo Cabinet/Tyrant、Redis、Voldemort、Berkeley DB
    • 典型应用: 内容缓存,主要用于处理大量数据的高访问负载。
    • 数据模型: 一系列键值对
    • 优势: 快速查询
    • 劣势: 存储的数据缺少结构化
  • 列存储数据库
    • 相关产品:Cassandra, HBase, Riak
    • 典型应用:分布式的文件系统
    • 数据模型:以列簇式存储,将同一列数据存在一起
    • 优势:查找速度快,可扩展性强,更容易进行分布式扩展
    • 劣势:功能相对局限
  • 文档型数据库
    • 相关产品:CouchDB、MongoDB
    • 典型应用:Web应用(与Key-Value类似,Value是结构化的)
    • 数据模型: 一系列键值对
    • 优势:数据结构要求不严格
    • 劣势: 查询性能不高,而且缺乏统一的查询语法
  • 图形(Graph)数据库
    • 相关数据库:Neo4J、InfoGrid、Infinite Graph
    • 典型应用:社交网络
    • 数据模型:图结构
    • 优势:利用图结构相关算法。
    • 劣势:需要对整个图做计算才能得出结果,不容易做分布式的集群方案。

1.2 Redis 介绍

1.2.1 Redis 简介

  • Redis 是一个开源的使用 ANSI C 语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库。

1.2.2 Redis 的应用场景

  • 缓存(数据查询、短连接、新闻内容、商品内容等等)
  • 聊天室的在线好友列表
  • 任务队列。(秒杀、抢购、12306等等)
  • 应用排行榜
  • 网站访问统计
  • 数据过期处理(可以精确到毫秒)
  • 分布式集群架构中的session分离

1.2.3 Redis 的安装步骤

  1. 安装Redis的gcc环境

    $ yum install gcc-c++
    
  2. 上传Redis文件并解压Redis压缩文件

    $ tar -zxvf redis-3.0.0.tar.gz 
    
  3. 进入解压后的目录进行编译和安装

    $ make && make install
    
  4. 测试 Redis 是否安装成功

    $ redis-server
    

    Tips:Redis安装之后,我们在/usr/local/bin下可以发现编译之后的Redis执行文件。bin目录下的文件在任何路径都可以启动,相当于帮我们配置了环境变量。

  5. 建立俩个文件夹存放redis命令和配置文件

    $ mkdir -p /usr/local/redis/etc
    $ mkdir -p /usr/local/redis/bin
    
  6. 把redis-3.0.0下的redis.conf 移动到/usr/local/redis/etc下

    $ cp /usr/local/redis-3.0.0/redis.conf ./
    
  7. 把/usr/local/bin下编译出来的 redis 执行文件(或者是redis-3.0.0/src中的执行文件)移动到 bin 下

    $ cd /usr/local/redis/bin
    $ cp /usr/local/bin/* ./ 
    
  8. 启动时并指定配置文件

    $  ./redis-server /usr/local/redis/etc/redis.conf 
    
  9. 验证启动是否成功

    # 查看是否有redis服务 或者 查看端口
    $ ps -ef | grep redis
    $ netstat -tunpl | grep 6379
    

1.2.4 redis 的启动与停止

  • Redis 的启动

    • 前端模式启动
      • 直接运行 redis-service 将以前端模式启动,前端模式启动的缺点是占用终端,同时 ssh 命令窗口关闭则 redis-service 程序结束,所以不推荐使用此方法。
    • 后端模式启动
      • 修改 redis.conf 配置文,将deamonize设置为yes 以后即可以后端模式来启动 Redis。
      • 修改之后用当前修改的配置文件来启动 Redis 服务器。
  • Redis 的停止

    • 要停止正在运行的 Redis 服务,可以采用 Linux 命令的方式直接杀掉 Redis 服务的进程,也可以使用 Redis 客户端向服务器发送 shutdown 指令来关闭 Redis 服务器
    $ cd /usr/local/redis/bin
    # 采用 Linux 命令的方式直接杀掉 Redis 服务的进程-->  kill -9 1781
    $  ./redis-cli shutdown
    # 关闭指定端口的 redis-server
    $ redis-cli -p 6379 shutdown
    
  • 启动 多个 redis 进程

    • 启动多个 redis 服务,一般采用定义多个对应的配置文件的方式来启动不同配置的 Redis 服务,同时需要分别修改每一个 Redis 服务器启动的端口号。

    • 这里我们启动两个 Redis 服务器,分别使用 6379 和 6380 端口。

      $ cp -r redis 6379
      $ cp -r redis 6380
      # 修改 6380 中的配置文件,将默认端口改为6380
      $ vim /etc/local/6380/etc/redis.conf
      # 分别启动两个 redis 服务
      $ cd /usr/local/6379/bin
      $  ./redis-server /usr/local/6379/etc/redis.conf 
      $ cd /usr/local/6380/bin
      $  ./redis-server /usr/local/6380/etc/redis.conf 
      # 查看两个redis 是否正常启动
      $  ps -ef|grep redis
      

1.2.5 解决最新redis 安装报错

因为使用后续案例使用 redis-3.0.0有问题,考虑是否是版本导致语法不支持的因素,就此重新安装了 redis-6.0.5,但是安装过程发现和旧版本不一样,按照原先的步骤进行安装会报错,所以在此记录一下解决方案。传送门

  1. 解压软件包,并进入解压后的目录

    $ rz redis-6.0.5.tar.gz
    $ tar -zxvf redis-6.0.5.tar.gz
    
  2. 使用make 命令编译软件时报错,解决方案是更高版本的GCC

    # 安装scl源
    $ yum install centos-release-scl scl-utils-build
    # 安装8版本的gcc、gcc-c++、gdb工具链
    $ yum install -y devtoolset-8-toolchain
    # 查看版本
    $ scl enable devtoolset-8 bash
    $ gcc --version
    
  3. 再次使用make 命令进行编译,可用命令 make test 进行测试下(该步骤可选)

    $ make
    $ make test
    # make test过程中可能缺少tcl的依赖包
    $ yum install tcl
    
  4. 查看READ.MD可知,没有 make install 命令,现在让我们启动 redis

    $ /usr/local/redis-6.0.5/src
    $  ./redis-server 
    

1.3 redis.conf配置文件基本说明

#是否以后台守护进程方式运行
daemonize yes|no

#pid 文件位置
pidfile /var/run/redis.pid

#监听的端口号
port 6379

# 请求超时时间
timeout 0

#log 信息级别,总共支持四个级别:debug、verbose、notice、warning, 默认为 verbose
loglevel notice

#默认为标准输出(stdout),如果配置为守护进程方式运行,而这里又配 置为日志记录方式为标准输出,则日志将会发送给/dev/null
logfile ""

#开启数据库的数量。使用“SELECT 库 ID”方式切换操作各个数据库
databases 16

#保存快照的频率,第一个*表示多长时间,第二个*表示执行多少次写操 作。在一定时间内执行一定数量的写操作时,自动保存快照。可设置多个条件。
# 使用格式: save <seconds> <changes>
save 900 1

#保存快照是否使用压缩
rdbcompression yes

#数据快照文件名(只是文件名,不包括目录)。默认值为 dump.rdb
dbfilename dump.rdb
#数据快照的保存目录(这个是目录)
dir ./

#设置 Redis 连接密码,如果配置了连接密码,客户端在连接 Redis 时需 要通过 AUTH <password>命令提供密码,默认关闭。
# 去掉行前的注释,并修改密码为所需的密码,保存文件
requirepass password

1.4 使用 Redis 客户端

在 Redis 的安装目录中有 redis 的客户端,即redis-cli(Redis Command Line Interface),它是 Redis 自带的基于命令行的 Redis 客户端。

1.4.1 连接 Redis 服务器

  • 使用redis-cli 命令即可连接默认的本机6379 端口的 Redis 服务器
  • 也可以远程连接其他主机或者其他端口的 Redis 服务器,使用-h设置远程主机的IP,-p设置远程主机的端口号

1.4.2 向 Redis 服务器发送命令

  • ping命令

    • Redis 提供了PING 命令来测试客户端与Redis 的连接是否正常,如果正常会收到回复PONG,见上图
  • set/get命令

    • 使用 set 和 get 可以向redis 设置数据、获取数据

  • del命令

    • del 命令用来删除指定 key 的内容

  • keys *命令

    • keys* 命令用来查看当前 redis 数据库中存在的 key 的名称

  • flushdb命令

    • flushed 命令用来清空当前数据库中的所有数据

  • 扩展指令

    • DBSIZE:返回当前数据库 key 的数量。
    • INFO:返回当前 redis 服务器状态和一些统计信息。
    • MONITOR:实时监听并返回redis服务器接收到的所有请求信息 。
    • SHUTDOWN:把数据同步保存到磁盘上,并关闭redis服务。
    • CONFIG GET parameter: 获取一个 redis 配置参数信息。(个别参数可能无法获取)
    • CONFIG SET parameter value: 设置一个 redis 配置参数信息。(个别参数可能无法获取)
    • CONFIG RESETSTAT: 重置 INFO 命令的统计信息。 (重置包括:Keyspace 命中数、 Keyspace 错误数、 处理命令数,接收连接数、过期 key 数)
    • DEBUG OBJECT key:获取一个 key 的调试信息。
    • DEBUG SEGFAULT:制造一次服务器当机。
    • FLUSHDB: 删除当前数据库中所有 key,此方法不会失败。小心慎用
    • FLUSHALL: 删除全部数据库中所有 key,此方法不会失败。小心慎用

1.4.3 Redis 多数据库

一个 Redis 数据库可以包含多个数据库,客户端可以指定连接某个 redis 实例的哪个数据库,就好比一个 mysql 中创建多个数据库,客户端连接时指定连接哪个数据库。一个reids 实例中默认提供16个数据库,这由启动的配置文件中指定,下表从015,客户端默认连接第0号数据库,也可以通过 select选择连接哪个数据库,不同数据库中的数据不能共享。

需要注意的问题是,如果我们使用flushall命令清空某一个库中的数据时,其他库中的数据也会被清空,因此,在我们不同的业务访问 Redis 服务器时应该选择不同的redis 服务器,而不是同一个服务器内部的不同的数据库。

1.5 Jedis 的使用

1.5.1 Jedis 介绍

Redis 不仅是使用命令来操作,现在基本上主流的语言都有客户端支持,比如 Java、C、C++、PHP、Node.js、Go等。在官方网站里列出一些 Java 的客户端,有 Jedis、Redission、Jredis、JDBC-Redis等,官方推荐使用 Jedis 和 Redisson。在企业中用的最多的就是 Jedis。

1.5.2 通过 Jedis 连接 Redis

  • 添加 Jedis 的 jar 包依赖

    <dependency>
    	<groupId>redis.clients</groupId>
    	<artifactId>jedis</artifactId>
    	<version>2.7.0</version>
    </dependency>
    
  • 单实例连接Redis

    /*
     * 过创建单实例jedis对象连接redis服务,直接创建Jedis对象即可
     */
    @Test
    public void testJedis(){
        // 远程链接的redis服务器的主机名称
        String host = "192.168.30.200";
        // 远程链接的redis服务器的端口
        int port = 6379;
        // 要使用Jedis进行Redis服务器的链接,需要首先获取Jedis对象
        Jedis jedis = new Jedis(host, port);
        	
      	//如果服务器设置了认证需要首先进行认证处理
    		//jedis.auth("redis");
      
        //使用redis命令进行操作
        String ping = jedis.ping();
        System.out.println(ping);
      
        // 使用jedis对象执行对应的指令完成redis的操作
        String ss = jedis.set("name", "silhouette");
        System.out.println("set方法的返回值:"+ss);
      
        // 进行取值操作,使用get方法
        String name = jedis.get("name");
        System.out.println("name:" + name);
      
        //进行删除操作
        Long del = jedis.del("name");
        System.out.println("删除的数据条数:"+del);
      
        //删除后取值
        name = jedis.get("name");
        System.out.println(name);
      
        //选择数据库
        jedis.select(1);
      
        //设置数据
        jedis.set("info", "this is a message");
      
        //取值
        String info = jedis.get("info");
        System.out.println(info);
      
        //清空当前库中的数据
        jedis.flushDB();
      
        //清空所有库中的数据
        jedis.flushAll();
      
        //jedis是一个与服务器的连接,肯定需要消耗资源
        jedis.close();
    }
    
  • 使用连接池连接 Redis

    /*
     * 通过单实例连接redis不能对redis连接进行共享
     * 可以使用连接池对redis连接进行共享,提高资源利用率,使用jedisPool连接redis服务
     */
    @Test
    public void testJedisPool(){
        //使用连接池访问redis,首先要创建连接池对象,首先配置连接池的参数
        GenericObjectPoolConfig poolConfig = new JedisPoolConfig();
      
        //设置连接池的最大连接数
        poolConfig.setMaxTotal(20);
        //设置连接池的最大连接空闲数
        poolConfig.setMaxIdle(2);
      
        String host ="192.168.30.200";
        int port = 6379;
        JedisPool jedisPool = new JedisPool(poolConfig, host, port);
      
        //获取Jedis对象
        Jedis jedis = jedisPool.getResource();
        // 进行redis数据库的交互操作
        System.out.println(jedis.set("pool", "jedisPool"));
        System.out.println(jedis.get("pool"));
      
        //进行认证
        //jedis.auth("redis");
      
        //使用jedis对象进行数据的操作
        jedis.set("msg","message");
      
        //取值操作
        System.out.println(jedis.get("msg"));
      
        //关闭资源
        jedisPool.close();
    }