Redis基础入门总结

    技术2023-05-14  73

    NoSQL非关系型数据库

    NoSQL概念

    Not Only SQL:不仅仅是SQL,指的就是非关系型数据库,它是关系型数据库有益的补充。最终的数据还是保存在关系型数据库中。非关系型数据库主要是提升数据库的查询速度,一般做为数据的缓存来使用。

    非关系型数据库

    ​ 非关系型数据库严格上不是一种数据库,应该是一种数据结构化存储方法的集合,可以是文档或者键值对等。

    优点
    格式灵活:存储数据的格式可以是key,value形式、文档形式、图片形式等等,使用灵活,应用场景广泛,而关系型数据库则只支持基础类型。速度快:nosql可以使用硬盘或者随机存储器作为载体,而关系型数据库只能使用硬盘;成本低:nosql数据库部署简单,基本都是开源软件。
    缺点
    不提供sql支持,学习和使用成本较高;数据结构相对复杂,复杂查询方面不方便。

    为什么要使用NOSQL

    具体表现为对如下三高问题的解决:

    High Performance - 数据库高并发访问

    ​ 在同一个时间点,同时有海量的用户并发访问。往往要达到每秒上万次读写请求。关系数据库应付上万次SQL查询还勉强顶得住,但是应付上万次SQL写数据请求,硬盘IO就已经无法承受了。

    如天猫的双11,从凌晨0点到2点这段时间,每秒达到上千万次的访问量。

    12306春运期间,过年回家买火车抢票的时间,用户不断查询有没有剩余票。

    Huge Storage - 海量数据的存储

    ​ 数据库中数据量特别大,数据库表中每天产生海量的数据。

    ​ 类似QQ,微信,微博,每天用户产生海量的用户动态,每天产生几千万条记录。对于关系数据库来说,在一张几亿条记录的表里面进行SQL查询,效率是极其低下乃至不可忍受的。

    High Scalability && High Availability- 高可扩展性和高可用性的需求

    ​ 关系型数据库进行扩展和升级是比较麻烦的一样事,对于很多需要提供24小时不间断服务的网站来说,对数据库系统进行升级和扩展是非常痛苦的事情,往往需要停机维护和数据迁移。

    ​ 非关系型数据库可以通过不断的添加服务器节点来实现扩展,而不需对原有的数据库进行维护。

    Redis的目录文件

    目录或文件作用redis-benchmark.exe用于性能测试一个工具命令redis-check-aof.exeAOF文件的检查和修复工具 (AOF是它的一种文件存储格式)redis-check-dump.exeRDB文件的检查和修改工具 (RDB是它的一种文件存储格式)redis-cli.exe客户端启动程序redis-server.exe服务器端启动程序 (不会自动启动,默认每次都要手动开启)redis.window.conf服务器配置文件

    string类型的操作命令

    Redis的5种数据类型

    redis是一种高级的key-value的存储系统,其中value支持五种数据类型,指的是它值的类型,键可以认为是字符串类型。redis不是用Java写的,是C语言写的。

    值的数据类型说明string类型字符串list类型列表:元素可以重复,元素是有索引号,有先后顺序的set类型集合:元素是不可重复的,元素没有索引号,没有先后顺序的hash类型值由多个键值对组成zset类型集合:元素不可重复的,每个元素有索引号,还有一个分数值,可以根据分数进行排序

    字符串类型string

    在Redis中以二进制保存,没有编码和解码的过程。

    无论存入的是字符串、整数、浮点类型都会以字符串写入。

    在Redis中字符串类型的值最多可以容纳的数据长度是512M,这是以后最常用的数据类型。

    常用命令

    命令功能set 键 值存入字符串类型的键和值,如果键不存在就是添加,存在就是修改setnx 键 值键不存在就是添加,存在不做任何操作,不会覆盖以前的键和值get 键通过键获取值del 键通过键删除键和值

    list类型的操作命令

    概述

    在Redis中,List类型是按照插入顺序排序的字符串链表。和数据结构中的普通链表一样,我们可以在其左部(left)和右部(right)添加新的元素。

    在插入时,如果该键并不存在,Redis将为该键创建一个新的链表。

    如果链表中所有的元素均被移除,那么该键也将会被从数据库中删除。

    List中可以包含的最大元素数量是4G个(41亿个)

    常用命令

    命令行为lpush 键 元素 元素从左边添加1个或多个元素rpush 键 元素 元素从右边添加1个或多个元素lpop 键删除最左边的一个元素,并且返回rpop 键删除最右边的一个元素,并且返回lrange 键 开始 结束查找指定索引范围内元素返回,每个元素有2个索引号索引号从左向右:0~length-1索引号从右向左:-1~-length如果要获取整个列表中所有的元素,索引号范围如何写?0~-1llen 键获取列表中有多少个元素

    命令演示

    一个Redis服务器可以包括多个数据库,客户端可以只连接Redis中某个数据库,就好比一个mysql服务器中创建多个数据库,客户端连接时指定连接到哪个数据库。

    Redis中有db0-db15编号的16个数据库。我们不能创建新的数据库,也不能删除数据库。数据库中也没有表的结构,客户端默认连接第0个数据库。但可以通过配置文件设定有多少个数据库。

    Jedis类常用方法

    每个方法就是redis中的命令名,方法的参数就是命令的参数。

    每个Jedis对象似于JDBC中Connection对象,获取一个Jedis对象本质上就是获取一个连接对象。

    连接和关闭功能new Jedis(String host, int port)创建一个连接对象参数1:主机名参数2:端口号 6379void close()关闭连接 对string操作的方法说明set(String key,String value)添加字符串类型的键和值String get(String key)通过键获取值del(String … keys)删除一个或多个键和值 对list操作的方法说明lpush(String key,String…values)从左边添加1个或多个元素List<String> lrange(String key,long start,long end)获取一个范围内所有的元素

    代码

    package com.itheima; import redis.clients.jedis.Jedis; /** * Jedis的基本使用 */ public class Demo1Base { public static void main(String[] args) { //1.创建Jedis连接对象 Jedis jedis = new Jedis("localhost", 6379); //2.向服务器添加1个字符串类型的键和值 jedis.set("book","人鬼情喂鸟"); //3.从服务器中通过键获取值 String book = jedis.get("book"); //4.关闭连接 jedis.close(); //5.打印输出到控制台 System.out.println(book); } }

    Jedis连接池的使用

    ​ jedis连接资源的创建与销毁是很消耗程序性能,所以jedis为我们提供了jedis的连接池技术,jedis连接池在创建时初始化一些连接对象存储到连接池中,使用jedis连接资源时不需要自己创建jedis对象,而是从连接池中获取一个资源进行redis的操作。使用完毕后,不需要销毁该jedis连接资源,而是将该资源归还给连接池,供其他请求使用。

    Jedis连接池API

    用于创建连接池的配置信息

    JedisPoolConfig配置类功能说明JedisPoolConfig()构造方法,创建一个配置对象void setMaxTotal()连接池中最大连接数void setMaxWaitMillis()设置最长等待时间,单位是毫秒 JedisPool连接池类说明JedisPool(配置对象,服务器名,端口号)构造方法,创建连接池的类参数1:上面的配置对象参数2:服务器名参数3:端口号Jedis getResource()从连接池中获取一个创建好的连接对象,返回Jedis对象

    JedisPool的基本使用

    需求:

    ​ 使用连接池优化jedis操作,从连接池中得到一个创建好的Jeids对象,并且使用这个Jedis对象。向Redis数据库写入一个set集合,并且取出集合。打印到控制台,并且查看数据库中信息。

    开发步骤

    创建连接池配置对象,设置最大连接数10,设置用户最大等待时间2000毫秒通过配置对象做为参数,创建连接池对象从连接池里面获取jedis连接对象,执行redis命令。执行redis命令写入list集合执行redis命令读取list集合输出读取的数据关闭连接对象(通常连接池不关闭)

    执行代码

    package com.itheima; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; import java.util.List; /** * Jedis连接池的基本使用 */ public class Demo2Pool { public static void main(String[] args) { //1.创建连接池的配置对象 JedisPoolConfig config = new JedisPoolConfig(); //2.设置连接池的参数 config.setMaxTotal(10); //最大连接数 config.setMaxWaitMillis(2000); //最长等待时间为2秒钟 //3.创建连接池,使用上面配置对象 JedisPool pool = new JedisPool(config,"localhost", 6379); //4.从连接池中获取连接对象 Jedis jedis = pool.getResource(); //5.使用连接对象 jedis.lpush("students", "孙悟空", "猪八戒", "白骨精"); List<String> students = jedis.lrange("students", 0, -1); System.out.println(students); //6.关闭连接对象 jedis.close(); } }

    小结

    JedisPool连接池类作用JedisPool(配置对象,服务器名,端口号)创建连接池参数1:配置对象参数2:服务器名参数3:端口号Jedis getResource()从连接池中获取连接对象void close()关闭连接池

    ResourceBundle类的使用

    代码

    jedis.properties的内容

    # 连接池的最大连接数 maxTotal=10 # 最长等待时间为2秒钟 maxWaitMillis=2000 # 服务器名字 host=localhost # 端口号 port=6379

    使用ResourceBundle类:

    package com.itheima; import java.util.ResourceBundle; public class Demo3Resource { public static void main(String[] args) { //1. 通过静态方法读取属性文件,参数是:属性文件的主文件名,没有扩展名 ResourceBundle bundle = ResourceBundle.getBundle("jedis"); //2. 获取属性值,通过键获取值 String host = bundle.getString("host"); //3.输出值 System.out.println(host); } }

    小结

    java.util.ResourceBundle类功能static ResourceBundle getBundle(“配置文件基名”)读取配置文件,得到对象。参数是主文件名String getString(“键名”)通过键获取值

    Jedis连接池工具类的实现

    jedis.properties配置文件

    # 主机名 host=localhost # 端口号 port=6379 # 最大连接数 maxTotal=20 # 最长等待时间 maxWaitMillis=3000

    JedisUtils.java

    package com.itheima.utils; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; import java.util.ResourceBundle; /** * Jedis连接池工具类 */ public class JedisUtils { private static JedisPool pool; //在静态代码块中创建连接池 static { //读取配置文件 ResourceBundle bundle = ResourceBundle.getBundle("jedis"); //读取属性值 int maxTotal = Integer.parseInt(bundle.getString("maxTotal")); int maxWaitMillis = Integer.parseInt(bundle.getString("maxWaitMillis")); int port = Integer.parseInt(bundle.getString("port")); String host = bundle.getString("host"); //创建连接池配置对象 JedisPoolConfig config = new JedisPoolConfig(); //设置连接池的参数 config.setMaxTotal(maxTotal); config.setMaxWaitMillis(maxWaitMillis); //创建连接池 pool = new JedisPool(config, host, port); } /** * 获取连接对象 */ public static Jedis getJedis() { return pool.getResource(); } }

    使用工具类

    package com.itheima; import com.itheima.utils.JedisUtils; import redis.clients.jedis.Jedis; //使用连接池工具类 public class Demo4Use { public static void main(String[] args) { //从连接池中获取连接对象 Jedis jedis = JedisUtils.getJedis(); //添加键和值 jedis.set("car", "BWM"); //取出 String car = jedis.get("car"); //输出 System.out.println(car); //关闭连接 jedis.close(); } }

    持久化

    利用永久性存储介质将数据进行保存,在特定的时间将保存的数据进行恢复的工作机制称为持久化 持久化用于防止数据的意外丢失,确保数据安全性

    永久化介质保存数据,存在硬盘

    RDB

    直接拷贝数据从内存到磁盘上

    RDB优点

    RDB是一个紧凑压缩的二进制文件,存储效率较高

    RDB内部存储的是redis在某个时间点的数据快照,非常适合用于数据备份,全量复制等场景

    RDB恢复数据的速度要比AOF快很多

    应用:服务器中每X小时执行bgsave备份,并将RDB文件拷贝到远程机器中,用于灾难恢复。

    RDB缺点

    RDB方式无论是执行指令还是利用配置,无法做到实时持久化,具有较大的可能性丢失数据

    bgsave指令每次运行要执行fork操作创建子进程,要牺牲掉一些性能

    Redis的众多版本中未进行RDB文件格式的版本统一,有可能出现各版本服务之间数据格式无法兼容现象

    AOF

    AOF(append only file)持久化:以独立日志的方式记录每次写命令,重启时再重新执行AOF文件中命令 达到恢复数据的目的。与RDB相比可以简单理解为由记录数据改为记录数据产生的变化

    AOF的主要作用是解决了数据持久化的实时性,目前已经是Redis持久化的主流方式

    AOF写数据三种策略(appendfsync)

    always(每次):每次写入操作均同步到AOF文件中 数据零误差,性能较低,不建议使用。

    everysec(每秒):每秒将缓冲区中的指令同步到AOF文件中,在系统突然宕机的情况下丢失1秒内的数据 数据准确性较高,性能较高,建议使用,也是默认配置

    no(系统控制):由操作系统控制每次同步到AOF文件的周期 整体过程不可控

    RDB VS AOF

    RDB与AOF的选择之惑

    对数据非常敏感,建议使用默认的AOF持久化方案

    AOF持久化策略使用everysecond,每秒钟fsync一次。该策略redis仍可以保持很好的处理性能,当出 现问题时,最多丢失0-1秒内的数据。

    注意:由于AOF文件存储体积较大,且恢复速度较慢

    数据呈现阶段有效性,建议使用RDB持久化方案

    数据可以良好的做到阶段内无丢失(该阶段是开发者或运维人员手工维护的),且恢复速度较快,阶段 点数据恢复通常采用RDB方案

    注意:利用RDB实现紧凑的数据持久化会使Redis降的很低,慎重总结:

    综合比对

    RDB与AOF的选择实际上是在做一种权衡,每种都有利有弊 如不能承受数分钟以内的数据丢失,对业务数据非常敏感,选用AOF

    如能承受数分钟以内的数据丢失,且追求大数据集的恢复速度,选用RDB

    灾难恢复选用RDB

    双保险策略,同时开启RDB 和 AOF,重启后,Redis优先使用AOF 来恢复数据,降低丢失数据的量

    以上内容有失偏颇处,欢迎指正!

    Processed: 0.010, SQL: 9