Redis

关系型数据库 数据直接存储到硬盘上的 mysql IO操作耗性能
缓存 基于内存 mybatis
非关系型数据库 NoSql
redis充当缓存,减轻数据库的压力

1. 关系型数据库和非关系型数据库区别

NoSql的优点

  • 部署简易,免费开源,成本低
  • 查询速度快: NoSql将数据存储在内存中,关系型数据库是把数据存储在硬盘当中
  • 存储数据的格式不相同: NoSql存储数据的格式基本是key-value,文档型,图片,还可以存储对象和集合类型等.关系型数据库大多数存储基本类型
  • 扩展性: 在关系型数据库中进行多表查询时扩展性较差

1.1 主流的NoSql数据库产品(了解)

  • key-value存储数据库
    Redis,DB
    应用: 一般用于内容缓存,解决大量数据高访问负载.
    数据模型: 一系列的key-value
    优势: 查询速度非常快
    劣势: 存储的数据缺少结构化
  • 列存储数据库
    Hbase
    典型应用: 用于分布式的文件系统
    数据模型: 以列簇的形式进行存储,将同一列数据存储在一起
    优势: 查询速度非常快,可扩展性较强,容易进行分布式部署
    劣势: 功能局限性较大
  • 文档型数据库
    MongoDB
    典型应用: 主要应用在web应用中,和key-value类似,value是结构化的
    数据模型: 是一系列的key-value
    优势: 数据结构要求不严格
    劣势: 查询速度不高,并且缺乏统一的查询语法
  • 图像数据库
    Graph Neo4J
    典型应用: 用于社交网络
    数据模型: 图结构
    优势: 利用图结构进行相关优化算法
    劣势: 需要对整个图进行计算才能得到结果,不容易进行分布式集群的使用

2. Redis

2.1 Redis概述

Redis是由C语言开发的一个开源的免费的键值对存储数据库,官方提供的数据库只有Linux版,对于50个并发,执行10万次请求,读的速度是110000次/s,写的速度81000次/s
它提供了多种键值类型满足多样化的需求,对于redis的键一般为字符串,对于值一般有5中类型
1)字符串类型string
2)散列类型hash
3)列表类型list
4)集合类型set
5)有序集合类型sorted set

2.2 Redis的使用场景

  • 令牌的生成 Token 类似于session中的sessionID
  • 短信验证码 code
  • 可以实现缓存查询数据,减轻数据库的压力
  • Redis帮助实现计数器
  • 做分布式锁
  • 延迟操作
  • 日志记录

2.3 Redis安装

官方推荐在Linux系统中进行安装的,当然也可以在Window系统中进行安装,Window版不是官方版本
因为Redis是由C语言开发的,所有需要安装C语言的编译环境,安装指令为 yun install gcc-c++
启动后默认端口是6379

按照指令

yum install gcc-c++
wget http://download.redis.io/releases/redis-5.0.7.tar.gz
#可能会提示wget命令找不到,执行yum -y install wget,然后再执行上面的指令
mv redis-5.0.7.tar.gz /usr/local/redis/redis-5.0.7.tar.gz
cd /usr/local/redis
tar -zxvf redis-5.0.7.tar.gz
cd reids-5.0.7
make
make install PREFIX=/usr/local/redis
#执行make时可能出现的问题,执行该命令make MALLOC=libc
在这里插入图片描述
然后再执行make install PREFIX=/usr/local/redis
cp redis.conf /usr/local/redis/bin
cd /usr/local/redis/bin
vim redis.conf
可能会提示vim指令找不到,执行yum -y install vim(建议使用,有高亮显示)
进入文件后输入 :set number
找到136行 把no改成yes
88行 把yes该成 no
69注释掉
保存退出 按下Esc键 :wq 回车键
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述./
在bin目录下,启动redis
./redis-server redis.conf
测试:
./redis-cli

Set a 100

Get a
跳出exit 回车键 / Ctrl C 键
关闭 : ./redis-cli shutdown

在这里插入图片描述

2.3.1 redis的开机自启

  • 创建文件

vim /etc/systemd/system/redis.service

  • 把以下内容写入该文件
[Unit]
Description=redis-server
After=network.target

[Service]
Type=forking
#对应自己的安装目录
ExecStart=/usr/local/redis/bin/redis-server /usr/local/redis/bin/redis.conf
PrivateTmp=true

[Install]
WantedBy=multi-user.target
  • 重启系统服务

systemctl daemon-reload

  • 关闭

systemctl stop redis.service

  • 开启

systemctl start redis.service

  • 服务加入开机自启

systemctl enable redis.service

  • 重启

reboot

  • 查看

ps -ef | grep redis

  • 其他命令

systemctl start redis.service #启动redis服务
systemctl enable redis.service #设置开机自启动
systemctl disable redis.service #停止开机自启动
systemctl status redis.service #查看服务当前状态
systemctl restart redis.service  #重新启动服务
systemctl list-units --type=service #查看所有已启动的服务

2.4 Redis数据结构

  • Redis是一种高级的key-value的数据库存储系统,其中key数据类型一般是string,value值支持5种数据类型:
    1)字符串类型string
    2)散列类型hash
    3)列表类型list
    4)集合类型set
    5)有序集合类型sorted set
  • 对于Redis的key值,如果定义的名称过长,查询效率会降低.

在这里插入图片描述

2.5 指令

前提
启动redis: 进入到 cd /usr/local/redis/bin里 启动redis ./redis-server redis.conf
然后./redis-cli

在这里插入图片描述

  • 测试连接是否成功 使用ping 成功会显示pong
  • Redis默认在空间中生成16个数据库,数据库编号依次从0-15,默认使用0号数据库
    使用select 索引值选择数据库 select 0~15
  • 显示所有的key使用 keys *
    使用指令 keys a? 查询a开头,长度位2的key
  • 使用flushall 清空所有数据
  • 删除key del key名称 , 删除多个key del key1 key2 ...
  • 校验key值是否存在 exists key 1代表存在,0代表不存在
  • 给key重命名 rename key旧名称 key新名称
  • 设置key过期时间 expire key 秒数
  • 查看key值得剩余得过期时间 ttl key ,如果key存在显示剩余的过期时间.如果没有设置过期时间显示 -1 ,如果key过时了或没有这个key显示-2
  • 查看key的指定数据类型(value) type key 返回值 string, hash, list ,set ,sorted set

2.6 string类型

字符串类型是redis数据库中最基础最常用的数据类型,并且在redis中是二进制安全的
该字符串类型可以接受任何类型的数据,在redis中字符串类型的value值最多可以容纳的数据长度位512M

设置键值对 set key value
设置多个键值对 mset key1 value1 key2 value2 ...
通过key取value值 get key (没有该key,返回nil)
删除key del key
先获取key的值,再设置key的值 getset key value
让key的值加1 ,incr key 默认加1
让key的值减1,decr key默认减1
增加值 incrby key 增加的值
减少值 decrby key 减少的值
在value后面追加 append key 信息,如果没有该key会自动新建该key并附上追加的信息

2.7 hash类型

散列类型可以看成map,key是string,value是一个map容器(key-value)

  • 赋值
    hset key field value 给指定的key设定field/value键值对值 设置一个
    hmset key field1 value1 fiels2 value2... 设置多个
  • 取值
    hget key field
    hmget key field1 fiels2 ...
  • 删除
    hdel key field1 field2 ...
    del key 删除所有
  • 增加
    hincrby key field 增加的数值
    hexists key field 判断指定的key中field是否存在
    hlen key 获取key所包含field的数量
    hkeys key 获取所有的key
    hvals key 获取所有value

2.8 list类型

在Redis中,list类型是安装插入顺序排序的字符串链表
和数据结构中的普通链表一样,我们在头部(left)和尾部(right)添加元素,在插入时,如果改键不存在,redis就会为该键创建一个新的链表;相反,如果该链表中所有元素均被移除,那么该键也会从数据库中移除
list中可以包含最大元素数量是42亿.
从元素插入和删除的效率来看,如果我们是在链表的两端插入和删除,效率非常高,如果从中间进行元素的插入和删除,那么效率较低

  • 两端添加
    lpush key value1 value2 ... 通过指定的key在头部存放多个value值,如果key不存在,那么就会创建一个与key关联的空链表,之后再把所有的value值插入该空链表的头部,插入成功,返回插入的元素个数
    rpush key value1 value2 ... 通过指定的key在尾部存放多个value值
    lpushx key value 仅当参数中指定的key存在时插入头部
    rpushx key value 仅当参数中指定的key存在时插入尾部
  • 查看列表
    lrange key start end 获取链表中从start到end的元素值 start , end 可以为负数,如果为-1表示链表尾部的元素,-2表示链表倒数第二个元素,以此类推
    在这里插入图片描述
  • 两端弹出(删除)
    lpop key 返回并弹出指定key关联的链表中的第一个元素,即头部元素
    在这里插入图片描述
    rpop key从尾部弹出元素
    在这里插入图片描述
    llen key 返回指定key关联链表中的元素个数
    linsert key before/after pivot value 在pivot元素前或后插入元素
    lset key 索引值 替换的值 按照索引值修改值
    ltrim key start end 删除区间以外的值
    sort key 如果值都时数字,可以1进行排序,不影响原来的内容

2.9 set类型

在redis中,我们可以把set类型理解为没有排序的字符集合.和list类型就一样了,我们也可以进行添加,删除或判断某个元素受否存在等
set可包含最大元素是42亿
和list类型不一样的是,set集合中不允许出现重复的元素
set集合还可以在服务器端进行聚合计算操作,如: unions,intersection,differences

sadd key value1 value2 value3 ... 添加,如果value值重复,则不会二次添加
smembers key 获取key中所有的成员
srem key member1 member2 ... 删除set中指定的成员
sismember key member 判断参数中指定成员是否存在该set中,返回值为1表示存在,返回0表示不存在
scard key 获取key中成员数量
srandmemeber key [count ]随机获取set中的成员

  • 和集合相关的
    sdiff key1 key2 返回key1 与 key2 中相差的成员,并且和key的顺序有关,返回的是差集
    sdiffstore destination key1 key2 将key1 key2相差的成员存储在destination(可以自己取名字)里面
    sinterstore destination key1 key2将交集存储在destination
    sunion key1 key2返回并集
    sunion destination key1 key2 返回并集并存储到destination

2.10 sorted set 类型

sorted set类型和set类型几乎一样,都是字符串的集合,都不允许元素重复;区别在于sorted set中每一个成员都会有一个分数(score)与之相关.
redis中正是通过分数来为集合中的每个成员进行从小到大排序
虽然sorted set 中的成员必须是唯一的,但是负数score是可以重复的
在sorted set添加/删除/修改一个成员时,速度较快
由于sorted set中的成员在集合中的位置是有序的,即便是访问位于集合中间的元素效率也是非常高的

zadd key score1 member1 score2 member2 ... 添加
zscore key member 返回分数
zcard key 集合的成员数量
zrem key member[member...] 删除
zrange key start end [withscores] 集合脚标为start end 的成员, [withscores] 成员的分数
zrevrange key start end [withscores] 按照分数从大到小的顺序返回索引从start end 中间的元素, [withscores] 成员的分数
zremrangebyrank key start end 按照排名顺序删除从后到前的元素
zremrangebyscore key start end 按照分数从小到大依次删除
zrangevyscore key min max [withscores] [limit offset count]
返回分数在[min,max]的成员,并按照分数从小到大进行排序
zcount key min max 获取分数在[min.max]成员个数
zincrby key increment member 设置指定成员的增加的分数
zrank key memeber 返回成员在集合中的排名

2.11 Redis持久化

redis是一个基于内存的缓存型数据库,当redis或重启时,那么存储在redis中的数据就会清除,所以我们需要将redis存储的数据进行持久化操作(即把数据存储到硬盘中),数据就会被永久性保存下来

redis的持久化机制

  • RDB机制(默认)
    redis默认使用该机制
    在一定的间隔时间内检测key值的变化情况,然后进行持久化,把数据存储到硬盘上,该配置在redis.conf文件
    在这里插入图片描述
  • AOF机制
    日志记录的方式,可以记录每一条命令的操作,可以在每一次命令操作后进行持久化操作
    编辑 vim /usr/local/redis/bin/redis.conf
    搜索 :/appendonly找到 appendonly no -->yes
    搜索 :/appendfsync找到 appendfsync everysec 每一秒进行一次持久化数据
    appendfsync always 每一次操作进行一次持久化
    appendfsync no 不进行持久化
    重启redis
    在这里插入图片描述

Java客户端连接Redis

redis不仅可以使用命令进行操作,也可以使用后端开发语言进行操作,市面上主流的语言基本都支持
有很多Java客户端 : Jedis,Redisson,Jredis等,目前企业中常用的时Jedis

开发步骤

  • 导包: maven坐标
    <!--Jedis  操作redis数据库-->
    <dependency>
      <groupId>redis.clients</groupId>
      <artifactId>jedis</artifactId>
      <version>2.7.2</version>
    </dependency>
        <!--导入redis连接池依赖-->
    <dependency>
      <groupId>commons-pool</groupId>
      <artifactId>commons-pool</artifactId>
      <version>1.3</version>
    </dependency>

构建Jedis客户端对象

Jedis jedis = new Jedis("ip地址","端口号,默认为6379");

使用Jedis的API方法

private Jedis jedis;

    /**
     * @author yxk
     * Date 2021/3/24 17:28
     * 练习string类型
     */
    @Test
    public void testRedis() {
        //给redis设置一个username
        jedis.set("username","zs");
        System.out.println(jedis.get("username"));
    }

    @Test
    public void test02() {
        jedis.set("gender","男");
        jedis.set("age","18");
        System.out.println(jedis.get("gender"));
        jedis.incrBy("age",20);
        jedis.expire("gender",10);
/*        try {
           Thread.sleep(11000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }*/
        System.out.println(jedis.ttl("gender"));
        //System.out.println(jedis.get("gender"));
        System.out.println(jedis.get("age"));
    }

    @Test
    public void test03() {
        jedis.mset("address","郑州","course","Java","num","43","birthday","2020-11-11");
        jedis.del("birthday","num");
        List<String> mget = jedis.mget("address", "course", "num", "birthday");
        for (String s : mget) {
            System.out.println(s);
        }
    }
    /**
     * @author yxk
     * Date 2021/3/24 17:28
     * 练习hash类型
     */
    @Test
    public void testHash01() {
        jedis.hset("people01","username","小孙");
        jedis.hset("people02","username","小明");
        jedis.hset("people01","age","15");
        jedis.hset("people01","gender","男");
        String username = jedis.hget("people01", "username");
        String age = jedis.hget("people01", "age");
        String gender = jedis.hget("people01", "gender");
        System.out.println("一个一个取值===============");
        System.out.println("姓名:"+username+",年龄:"+age+",性别:"+gender);
        jedis.expire("people01",5);
        jedis.ttl("people01");

        //获取hash所有的数据,一个map就是一个JavaBean
        Map<String, String> map = jedis.hgetAll("people01");
        System.out.println("一次取所有的值,返回map集合=============");
        System.out.println(map);
        //获取所有的value值
        System.out.println("一次取所有的值,返回list集合=============");
        List<String> hvals = jedis.hvals("people01");
        System.out.println(hvals);
        //

        //删除
        jedis.hdel("people01","username");
        System.out.println(jedis.hgetAll("people01"));

        //测试过期时间
        try {
            Thread.sleep(6000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(jedis.hgetAll("people01"));
    }

    /**
     * @author yxk
     * Date 2021/3/24 17:43
     * 练习list类型
     * lpush头部添加
     * rpush尾部添加
     * lpop头部删除
     * rpoop尾部删除
     * lrange start end 区间范围值
     * linsert 中间添加
     * llen 获取长度
     */
    @Test
    public void testList() {
        jedis.lpush("country","中国","美国","英国");
        jedis.lset("country",1,"类类");
        List<String> list = jedis.lrange("country", 0, 2);
        System.out.println(list);

        //删除区间以外的值
        jedis.ltrim("country",0,1);
        List<String> country = jedis.lrange("country", 0, 2);
        System.out.println(country);

        //如果内容为数字,可以进行排序,不会影响原来的顺序
        jedis.lpush("agesss","87","35","1","656","23");
        List<String> sort = jedis.sort("agesss");
        System.out.println(sort);
        List<String> ages = jedis.lrange("agesss", 0, 5);
        System.out.println(ages);
    }

    @Before
    public void before() {
        jedis = new Jedis("192.168.88.107", 6379);
    }

    @After
    public void after() {
        jedis.close();
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值