• Redis


    目录

    1、Nosql定义和分类 

    1.1什么是NoSql

    1.2NoSql的分类

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

    1.2.2列存储数据库

    1.2.3文档型数据库

    1.2.4图形(Graph)数据库

    2、Redis定义,历史和应用场景 

    2.1什么是redis

    2.2redis历史发展

    2.3redis的应用场景

    3、Redis下载和安装 

    3.1windows版下载和安装

    3.1.1Redis的目录结构

    3.1.2启动redis服务端

    3.1.3启动redis客户端

    3.1.4图形化界面客户端

    3.1.5指定配置启动redis服务

    3.2Linux版下载和安装

    3.2.1下载

    3.2.2安装

    3.2.3运行redis

    3.2.4后台启动

    3.2.5查看是否启动成功

    3.2.6关闭redis服务

    3.2.7使用桌面管理工具连接Linux redis

    3.2.8以服务方式启动redis

    3.3清缓存命令

    4、Redis的String数据类型的赋值取值删除 

    4.1命令

    4.1.1赋值

    4.1.2取值

    4.1.3取值并赋值

    4.1.4设置/获取多个键值 

    4.1.5删除

     4.1.6数值增减

    5、Redis的Hash数据类型的赋值取值删除 

    5.1使用string的问题

    5.2redis hash介绍

    5.3命令

    5.3.1赋值

    5.3.2取值 

    5.3.3删除字段

    5.3.4增加数字 

    6、Redis的List数据类型的赋值取值删除 

    6.2命令

    6.2.1向列表两端增加元素

    6.2.2查看列表 

    6.2.3从列表两端弹出元素 

    6.2.4获取列表中元素的个数 

    6.2.5可添加重复元素

    7、Redis的Set数据类型的赋值取值删除 

    7.1命令

    7.1.1增加/删除元素 

    ​7.1.2获得集合中的所有元素 

    7.1.3判断元素是否在集合中

    7.2运算命令

    7.2.1集合的差集运算 A-B

    7.2.2集合的交集运算 A ∩ B

    7.2.3集合的并集运算 A ∪ B

    8、Redis的SortedSet数据类型的赋值取值删除

    8.1Sortedset 

    8.2命令

    8.2.1增加元素

    8.2.2获取元素的分数 

    8.2.3删除元素

    8.2.4获得排名在某个范围的元素列表

    8.2.5获取元素的排名 

    9、Keys命令

    9.1常用命令

    9.1.1keys

     9.1.2exists

    9.1.3del

    9.1.4rename

    9.1.5type

    9.1.6设置key的生存时间

    10、SpringBoot整合Redis 

    10.1新建SpringBoot工程,引入Web,Redis的场景启动器

    10.2application.yml配置redis地址

    10.3在使用处注入StringRedisTemplate或者RedisTemplate

    10.3.1StringRedisTemplate

    简单的设值获取值

     HashOperations操作Hash类型的数据

     ListOperation操作List数据类型

    SetOperations 操作set类型数据

     ZSetOperations 操作 可以排序的集合类型

    10.3.2RedisTemplate

    10.3.2.1redisTemplate默认如果保存对象,使用jdk序列化机制

    ​10.3.2.2改变jdk的序列化规则  (RedisConfiguration)

    11、持久化

    11.1Redis持久化概述

    11.2RDB持久化

    1.redis.windows.conf配置文件

    2.重启服务器,并指定配置文件

    3.启动客户端

    4.重新启动服务器和客户端,不需要指定配置文件。

    11.3AOF持久化

    1.redis.windows.conf配置文件

    2.重启服务器,指定配置文件

    3.启动客户端,1秒持久化一次

    4.关闭并重启服务器(指定配置文件)和客户端,在客户端获取,结果如下:

    Redis为什么这么快?


    1、Nosql定义和分类 

    1.1什么是NoSql

    NoSql,叫非关系型数据库,它的全名Not only sql。为了解决高并发、高可用、高可扩展,大数据存储等一系列问题而产生的数据库解决方案,就是NoSql。它不能替代关系型数据库,只能作为关系型数据库的一个良好补充。

    1.2NoSql的分类

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

    相关产品: Tokyo Cabinet/Tyrant、Redis、Voldemort、Berkeley DB
    典型应用: 内容缓存,主要用于处理大量数据的高访问负载。 
    数据模型: 一系列键值对
    优势: 快速查询
    劣势: 存储的数据缺少结构化

    1.2.2列存储数据库

    相关产品:Cassandra, HBase, Riak
    典型应用:分布式的文件系统
    数据模型:以列簇式存储,将同一列数据存在一起
    优势:查找速度快,可扩展性强,更容易进行分布式扩展
     劣势:功能相对局限

    1.2.3文档型数据库

    相关产品:CouchDB、MongoDB
    典型应用:Web应用(与Key-Value类似,Value是结构化的)
    数据模型: 一系列键值对
     优势:数据结构要求不严格
     劣势: 查询性能不高,而且缺乏统一的查询语法

    1.2.4图形(Graph)数据库

    相关数据库:Neo4J、InfoGrid、Infinite Graph
    典型应用:社交网络
    数据模型:图结构
    优势:利用图结构相关算法。
    劣势:需要对整个图做计算才能得出结果,不容易做分布式的集群方案。

    2、Redis定义,历史和应用场景 

    2.1什么是redis

    Redis是使用c语言开发的一个高性能键值数据库。Redis可以通过一些键值类型来存储数据。
    键值类型:

    • String字符类型
    • map散列类型hash
    • list列表类型
    • set集合类型
    • sortedset有序集合类型

    2.2redis历史发展

        2008年,意大利的一家创业公司Merzia推出了一款基于MySQL的网站实时统计系统LLOOGG,然而没过多久该公司的创始人 Salvatore Sanfilippo便 对MySQL的性能感到失望,于是他决定亲自为LLOOGG量身定做一个数据库,并于2009年开发完成,这个数据库就是Redis。 不过Salvatore Sanfilippo并不满足只将Redis用于LLOOGG这一款产品,而是希望更多的人使用它,于是在同一年Salvatore Sanfilippo将Redis开源发布,并开始和Redis的另一名主要的代码贡献者Pieter Noordhuis一起继续着Redis的开发,直到今天。

        Salvatore Sanfilippo自己也没有想到,短短的几年时间,Redis就拥有了庞大的用户群体。Hacker News在2012年发布了一份数据库的使用情况调查,结果显示有近12%的公司在使用Redis。国内如新浪微博、街旁网、知乎网,国外如GitHub、Stack Overflow、Flickr等都是Redis的用户。

        VMware公司从2010年开始赞助Redis的开发, Salvatore Sanfilippo和Pieter Noordhuis也分别在3月和5月加入VMware,全职开发Redis。

    2.3redis的应用场景

    缓存(数据查询、短连接、新闻内容、商品内容等等)。(最多使用)
    分布式集群架构中的session分离。

    聊天室的在线好友列表。
    任务队列。(秒杀、抢购、12306等等)
    应用排行榜。
    网站访问统计。
    数据过期处理(可以精确到毫秒)

    3、Redis下载和安装 

    3.1windows版下载和安装

     window版下载地址:https://github.com/MicrosoftArchive/redis/releases
    下载Redis For  window X64.zip,解压到指定目录

    3.1.1Redis的目录结构

     

     Redis.windows.conf:redis的配置文件。文件内可以声明redis的端口号,database的数量,密码,是否后台运行,持久化机制,日志等信息。
    Redis-server.exe:redis服务端,可以启动redis服务。
    Redis-cli.exe: redis自带客户端,启动以后即可连接服务端,通过以命令的形式向redis服务中存取数据,也可以关闭redis服务。

    3.1.2启动redis服务端

    双击 redis-server.exe ,启动成功,出现如下界面。端口号6379,pid:16316,如果关闭当前窗口,相当于关闭redis服务。

    或者以命令行的方式启动redis,在当前目录下输入redis-server即可启动redis服务

    3.1.3启动redis客户端

    双击redis-cli.exe即可启动客户端:如下图表示,则已经连上服务端,可以通过命令存取数据了。
    如果服务端设置了密码,在运行客户端连接服务端时,需要加上密码
    ./redis-cli -a 123456  -------123456为密码

     或者

    3.1.4图形化界面客户端

    RedisDesktopManager以图形化界面的方式操作redis中的数据。安装redis桌面管理工具。
    建立连接:

    输入名称,主机ip,默认端口号6379,即可连接redis服务器。

     Redis默认有16个数据库,如果不指定,默认使用database0

       向第一个数据库中添加,修改,删除数据。

    3.1.5指定配置启动redis服务

    Redis启动时可以不指定配置文件,会使用默认配置启动。也可以指定配置文件。如果我们修改了配置文件的内容,希望指定以某个配置文件启动,则使用如下方法启动
    复制配置文件redis.windows.conf,改名为redis.conf,修改使用密码123456登录。

    以该配置文件运行redis服务:

    此时,再通过图形化客户端连接服务时,必须指定密码才可以,否则会连接失败。

    3.2Linux版下载和安装

    3.2.1下载

    官网:https://redis.io/download,选择稳定版本。

    3.2.2安装

    1.解压

    通过xftp把redis安装包上传到指定文件夹。

    解压:tar -zxvf redis-6.0.6.tar.gz

     

     2.安装

    由于redis依赖c语言环境,所以先安装gcc
    [root@localhost ~]# yum install gcc
    如果是线上下载安装包的话,先进入目录  usr/local,下载安装包
    [root@localhost local]# wget http://download.redis.io/releases/redis-6.0.6.tar.gz
    解压
    [root@localhost local]# tar -xvf redis-6.0.6.tar.gz
    安装好了c语言环境以后,需要编译redis,进入解压后的目录
    [root@localhost local]# cd /usr/local/redis-6.0.6/
    编译
    [root@localhost local]# make
    安装,如果不指明安装路径,就会在当前路径下安装,指明安装路径,会在指明的路径下生成bin文件夹,bin里面是redis的命令
    [root@localhost redis-6.0.1]# make PREFIX=/usr/local/redis-6.0.6 install

    进入bin

    注意:如果在编译的时候报错如下:等等,太长了,不列举了。
    m ake[1]: *** [server.o] 错误 1
    make[1]: 离开目录“/usr/redis-6.0.6/src”
    make: *** [all] 错误 2
    server.c:2402:11: 错误:‘struct redisServer’没有名为‘assert_file’的成员
         server.assert_file = "<no file>";
    server.c:2403:11: 错误:‘struct redisServer’没有名为‘assert_line’的成员
         server.assert_line = 0;
    server.c:2404:11: 错误:‘struct redisServer’没有名为‘bug_report_start’的成员
         server.bug_report_start = 0;

    解决办法:升级gcc版本
    [root@localhost redis-6.0.6]# gcc -v                             # 查看gcc版本
    [root@localhost redis-6.0.6]# yum -y install centos-release-scl  # 升级到9.1版本
    [root@localhost redis-6.0.6]# yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils
    [root@localhost redis-6.0.6]# scl enable devtoolset-9 bash
    以上为临时启用,如果要长期使用gcc 9.1的话:
    [root@localhost redis-6.0.6]# echo "source /opt/rh/devtoolset-9/enable" >>/etc/profile
    在执行编译就没有问题了,安装成功,会提示:

     

     执行make test,可能会出现如下错误:
    [root@localhost redis-6.0.6]# make test
    cd src && make test
    make[1]: 进入目录“/usr/redis-6.0.6/src”
        CC Makefile.dep
    make[1]: 离开目录“/usr/redis-6.0.6/src”
    make[1]: 进入目录“/usr/redis-6.0.6/src”
    You need tcl 8.5 or newer in order to run the Redis test
    make[1]: *** [test] 错误 1
    make[1]: 离开目录“/usr/redis-6.0.6/src”
    make: *** [test] 错误 2
    解决办法:
    [root@localhost redis-6.0.6]# yum install tcl
    [root@localhost redis-6.0.6]# make test
    重新测试成功。

    3.2.3运行redis

    以某个配置文件启动redis服务,一定要注意配置文件的路径

    3.2.4后台启动

    上面redis的启动方式,是前端启动,一关闭客户端,redis的服务也就停掉了,所以这种启动方式非常不友好。我们可以修改配置文件中的启动方式:
    [root@localhost redis-6.0.6]# vim redis.conf
    进到redis.conf文件里,然后找到daemonize no把no改为yes

     启动的时候指定修改之后的配置文件即可。

    3.2.5查看是否启动成功

    3.2.6关闭redis服务

     或者:

     如果redis设置了密码,则以下面方式关闭,123456为密码

    3.2.7使用桌面管理工具连接Linux redis

    修改redis配置文件,注释掉bind 127.0.0.1

     保护模式关闭:


    设置密码:

    3.2.8以服务方式启动redis

    1.把redis加入service服务
    vim /lib/systemd/system/redis.service
    2.写入
    [Unit]
    Description=redis
    After=network.target

    [Service]
    Type=forking
    PIDFile=/var/run/redis_6379.pid
    ExecStart=/usr/local/redis-6.0.6/src/redis-server /usr/local/redis-6.0.6/etc/redis.conf
    ExecReload=/bin/kill -s HUP $MAINPID
    ExecStop=/bin/kill -s QUIT $MAINPID
    PrivateTmp=true

    [Install]
    WantedBy=multi-user.target
    注意路径问题,以及PIDFile的路径对应的是redis-6.0.6/redis.conf里面的PIDFile
    保存,退出。

    3.运行以下

    [root@localhost redis-6.0.6]# systemctl enable redis.service          # 加入开机启动

    [root@localhost redis-6.0.6]# systemctl is-enabled redis.service      # 查看开机是否启动成功
    enabled

    [root@localhost redis-6.0.6]# systemctl start redis                 #开启redis服务

    [root@localhost redis-6.0.6]# systemctl status redis            //查看redis运行状态

    3.3清缓存命令

    把缓存键值对清空。

    4、Redis的String数据类型的赋值取值删除 

    4.1命令

    4.1.1赋值

    语法:set key value

    4.1.2取值

    语法:get key

    4.1.3取值并赋值

     语法:GETSET key value

    4.1.4设置/获取多个键值 

    语法:
    mset key value [key value …]

    mget key [key …]

    4.1.5删除

    语法:del key
    127.0.0.1:6379> del test
    (integer) 1

     4.1.6数值增减

    递增数字 
    当存储的字符串是整数时,Redis提供了一个实用的命令INCR(increate),其作用是让当前键值递增,并返回递增后的值。

    语法:incr key

     增加指定的整数
    语法:incrby key increment

     递减数值
    语法:decr key          可以减为负值

     减少指定的整数 
    语法:decrby key decrement

    5、Redis的Hash数据类型的赋值取值删除 

    散列类型

    5.1使用string的问题

        假设有User对象以JSON序列化的形式存储到Redis中,User对象有id,username、password、age、name等属性,存储的过程如下: 
    保存、更新: 
    User对象 --> json(string) --> redis 
    如果在业务上只是更新age属性,其他的属性并不做更新我应该怎么做呢? 如果仍然采用上边的方法在传输、处理时会造成资源浪费,下边讲的hash可以很好的解决这个问题。

    5.2redis hash介绍

        hash叫散列类型,它提供了字段名和字段值的映射。字段值只能是字符串类型,不支持散列类型、集合类型等其它类型。如下:

    5.3命令

    5.3.1赋值

    hset命令不区分插入和更新操作,执行插入操作时HSET命令返回1,执行更新操作时返回0。

    一次只能设置一个字段值
    语法:hset key field value  

     一次可以设置多个字段值
    语法:hmset key field value [field value ...]        

     当字段不存在时赋值,类似hset,区别在于如果字段存在,该命令不执行任何操作
    语法:hsetnx key field value
    如果user中没有age字段则设置age值为30,否则不做任何操作

    5.3.2取值 

    一次只能获取一个字段值
    语法:hget key field            

     一次可以获取多个字段值
    语法:hmget key field [field ...]                

     获取所有字段值
    语法:hgetall key

    5.3.3删除字段

    可以删除一个或多个字段,返回值是被删除的字段个数 

    语法:hdel key field [field ...]

    5.3.4增加数字 

    语法:hincrby key field increment

    6、Redis的List数据类型的赋值取值删除 

    Redis的list是采用来链表来存储的,所以对于redis的list数据类型的操作,是操作list的两端数据来操作的。

    6.2命令

    6.2.1向列表两端增加元素

    向列表左边增加元素 
    语法:lpush key value [value ...]

     向列表右边增加元素 
    语法:rpush key value [value ...]

    6.2.2查看列表 

    lrange命令是列表类型最常用的命令之一,获取列表中的某一片段,将返回start、stop之间的所有元素(包含两端的元素),索引从0开始。索引可以是负数,如:“-1”代表最后边的一个元素。

    语法:lrange key start stop

     127.0.0.1:6379> lrange list1 0 -1    查所有

     往左边存,先存1,lpush是往左边放,2放在1的左边,3放在2的左边,依次往前

    6.2.3从列表两端弹出元素 

    lpop命令从列表左边弹出一个元素,会分两步完成:
    第一步是将列表左边的元素从列表中移除
    第二步是返回被移除的元素值。

    语法:
    lpop key


    rpop key

    6.2.4获取列表中元素的个数 

    语法:llen key

    6.2.5可添加重复元素

     

    7、Redis的Set数据类型的赋值取值删除 

    集合类型

    集合类型:无序、不可重复
    列表类型:有序、可重复

    7.1命令

    7.1.1增加/删除元素 

    语法:sadd key member [member ...]

     语法:srem key member [member ...]


    7.1.2获得集合中的所有元素 

     语法:smembers key

    7.1.3判断元素是否在集合中

    语法:sismember key member

    7.2运算命令

    7.2.1集合的差集运算 A-B

    属于A并且不属于B的元素构成的集合。 

    语法:sdiff key [key ...]

    7.2.2集合的交集运算 A ∩ B

    属于A且属于B的元素构成的集合。 

    语法:sinter key [key ...]

    7.2.3集合的并集运算 A ∪ B

    属于A或者属于B的元素构成的集合


    语法:sunion key [key ...]

     

    8、Redis的SortedSet数据类型的赋值取值删除

    8.1Sortedset 

    Sortedset又叫zset

    Sortedset是有序集合,可排序的,但是唯一。

    Sortedset和set的不同之处,是会给set中的元素添加一个分数,然后通过这个分数进行排序。

    8.2命令

    8.2.1增加元素

        向有序集合中加入一个元素和该元素的分数,如果该元素已经存在则会用新的分数替换原有的分数。返回值是新加入到集合中的元素个数,不包含之前已经存在的元素。 

    语法:zadd key score member [score member ...]

    8.2.2获取元素的分数 

    语法:zscore key member

    8.2.3删除元素

    移除有序集key中的一个或多个成员,不存在的成员将被忽略。
    当key存在但不是有序集类型时,返回一个错误。

    语法:zrem key member [member ...]

    8.2.4获得排名在某个范围的元素列表

    获得排名在某个范围的元素列表 
    按照元素分数从小到大的顺序返回索引从start到stop之间的所有元素(包含两端的元素)

    语法:zrange key start stop [withscores]


    按照元素分数从大到小的顺序返回索引从start到stop之间的所有元素(包含两端的元素)

    语法:arevrange key start stop [withscores]        

    如果需要获得元素的分数的可以在命令尾部加上withscores参数 

    8.2.5获取元素的排名 

    从小到大
    语法:ZRANK key member

     从大到小
    语法:ZREVRANK key member

    9、Keys命令

    9.1常用命令

    9.1.1keys

    返回满足给定pattern 的所有key

     9.1.2exists

    确认一个key 是否存在
    示例:从结果来看,数据库中不存在HongWan 这个key,但是age 这个key 是存在的

    9.1.3del

    删除一个key

    9.1.4rename

    重命名key
    示例:k2成功的被我们改名为k2了

    9.1.5type

    返回值的类型
    示例:这个方法可以非常简单的判断出值的类型

    9.1.6设置key的生存时间

    Redis在实际使用过程中更多的用作缓存,然而缓存的数据一般都是需要设置生存时间的,即:到期后数据销毁。

    expire key seconds             设置key的生存时间(单位:秒)key在多少秒后会自动删除
    ttl key                                  查看key剩余的生存时间
    persist key                          清除生存时间  -1
    pexpire key milliseconds    生存时间设置单位为:毫秒

    -1:清除生存时间,redis一直存在该key
    -2:到期,redis没有该key
    正整数:剩余的生存时间

     

     手机号验证码

    10、SpringBoot整合Redis 

    10.1新建SpringBoot工程,引入Web,Redis的场景启动器

    1. <dependency>
    2. <groupId>org.springframework.boot</groupId>
    3. <artifactId>spring-boot-starter-data-redis</artifactId>
    4. </dependency>

    10.2application.yml配置redis地址

    10.3在使用处注入StringRedisTemplate或者RedisTemplate

    10.3.1StringRedisTemplate

    处理字符串相关操作


    简单的设值获取值

    1. package com.tjetc;
    2. import org.junit.jupiter.api.Test;
    3. import org.springframework.beans.factory.annotation.Autowired;
    4. import org.springframework.boot.test.context.SpringBootTest;
    5. import org.springframework.data.redis.core.HashOperations;
    6. import org.springframework.data.redis.core.StringRedisTemplate;
    7. import org.springframework.data.redis.core.ValueOperations;
    8. import java.util.Arrays;
    9. import java.util.HashMap;
    10. import java.util.List;
    11. import java.util.Map;
    12. @SpringBootTest
    13. class ApplicationTests {
    14. @Autowired
    15. private StringRedisTemplate stringRedisTemplate;
    16. @Test
    17. public void testString() {
    18. // System.out.println(stringRedisTemplate);
    19. ValueOperations<String, String> valueOperations = stringRedisTemplate.opsForValue();
    20. valueOperations.set("k1", "v1");
    21. valueOperations.set("k2", "v2");
    22. String v1 = valueOperations.get("k1");
    23. System.out.println(v1);
    24. //存储多对key和value
    25. Map<String, String> map = new HashMap<>();
    26. map.put("k3", "v3");
    27. map.put("k4", "v4");
    28. valueOperations.multiSet(map);
    29. }
    30. }

     


     HashOperations操作Hash类型的数据

    1. package com.tjetc;
    2. import org.junit.jupiter.api.Test;
    3. import org.springframework.beans.factory.annotation.Autowired;
    4. import org.springframework.boot.test.context.SpringBootTest;
    5. import org.springframework.data.redis.core.HashOperations;
    6. import org.springframework.data.redis.core.StringRedisTemplate;
    7. import org.springframework.data.redis.core.ValueOperations;
    8. import java.util.Arrays;
    9. import java.util.HashMap;
    10. import java.util.List;
    11. import java.util.Map;
    12. @SpringBootTest
    13. class ApplicationTests {
    14. @Autowired
    15. private StringRedisTemplate stringRedisTemplate;
    16. @Test
    17. public void testHash() {
    18. // HashOperations操作Hash类型的数据
    19. HashOperations<String, Object, Object> hashOperations = stringRedisTemplate.opsForHash();
    20. //存储单个字段名和字段值
    21. hashOperations.put("user", "username", "zhangsan");
    22. hashOperations.put("user", "age", "18");
    23. //存储多个字段名和字段值
    24. Map<String, String> map = new HashMap<>();
    25. map.put("sex", "男");
    26. map.put("email", "aaa.@163.com");
    27. hashOperations.putAll("user", map);
    28. //获取单个值
    29. Object username = hashOperations.get("user", "username");
    30. System.out.println("username" + username);
    31. //获取多个值
    32. List<Object> hashKeys = Arrays.asList("username", "age", "sex", "email");
    33. List<Object> user = hashOperations.multiGet("user", hashKeys);
    34. System.out.println("user的多个hash值:" + user);
    35. }
    36. }

     

     ListOperation操作List数据类型

    1. package com.tjetc;
    2. import org.junit.jupiter.api.Test;
    3. import org.springframework.beans.factory.annotation.Autowired;
    4. import org.springframework.boot.test.context.SpringBootTest;
    5. import org.springframework.data.redis.core.HashOperations;
    6. import org.springframework.data.redis.core.ListOperations;
    7. import org.springframework.data.redis.core.StringRedisTemplate;
    8. import org.springframework.data.redis.core.ValueOperations;
    9. import java.util.Arrays;
    10. import java.util.HashMap;
    11. import java.util.List;
    12. import java.util.Map;
    13. @SpringBootTest
    14. class ApplicationTests {
    15. @Autowired
    16. private StringRedisTemplate stringRedisTemplate;
    17. @Test
    18. public void testList() {
    19. // ListOperations 操作List数据类型的
    20. ListOperations<String, String> listOperations = stringRedisTemplate.opsForList();
    21. // 从左边添加一个数据
    22. listOperations.leftPush("list", "1");
    23. listOperations.leftPush("list", "2");
    24. // 从左边添加多个数据
    25. listOperations.leftPushAll("list", "3", "4");
    26. // 从右边添加一个数据
    27. listOperations.rightPush("list", "5");
    28. listOperations.rightPush("list", "6");
    29. // 从右边添加多个数据
    30. listOperations.rightPushAll("list", "7", "8");
    31. //获取所有数据
    32. List<String> list = listOperations.range("list", 0, -1);
    33. System.out.println(list);
    34. //从左边弹出数据
    35. String leftPopValue = listOperations.leftPop("list");
    36. System.out.println(leftPopValue);
    37. //从右边弹出数据
    38. String rightPopValue = listOperations.rightPop("list");
    39. System.out.println(rightPopValue);
    40. //再次获取全部数据
    41. List<String> list1 = listOperations.range("list", 0, -1);
    42. System.out.println(list1);
    43. }
    44. }

     

     

     List可重复添加        [二次刷新后]


    SetOperations 操作set类型数据

    1. package com.tjetc;
    2. import org.junit.jupiter.api.Test;
    3. import org.springframework.beans.factory.annotation.Autowired;
    4. import org.springframework.boot.test.context.SpringBootTest;
    5. import org.springframework.data.redis.core.*;
    6. import java.util.*;
    7. @SpringBootTest
    8. class ApplicationTests {
    9. @Autowired
    10. private StringRedisTemplate stringRedisTemplate;
    11. @Test
    12. public void testSet() {
    13. // SetOperations 操作set类型数据
    14. SetOperations<String, String> setOperations = stringRedisTemplate.opsForSet();
    15. //添加,可以添加多个值
    16. setOperations.add("setA", "a", "b", "c", "a");
    17. //获取所有值
    18. Set<String> setA = setOperations.members("setA");
    19. System.out.println("setA=" + setA);
    20. setOperations.add("setB", "b", "c", "d");
    21. Set<String> setB = setOperations.members("setB");
    22. System.out.println("setB=" + setB);
    23. //差集difference
    24. Set<String> difference = setOperations.difference("setA", "setB");
    25. System.out.println("setA差集setB:" + difference);
    26. //交集intersect
    27. Set<String> intersect = setOperations.intersect("setA", "setB");
    28. System.out.println("setA交集setB:" + intersect);
    29. //并集union
    30. Set<String> union = setOperations.union("setA", "setB");
    31. System.out.println("setA并集setB:" + union);
    32. }
    33. }

     

     


     ZSetOperations 操作 可以排序的集合类型

    1. package com.tjetc;
    2. import org.junit.jupiter.api.Test;
    3. import org.springframework.beans.factory.annotation.Autowired;
    4. import org.springframework.boot.test.context.SpringBootTest;
    5. import org.springframework.data.redis.core.*;
    6. import java.util.*;
    7. @SpringBootTest
    8. class ApplicationTests {
    9. @Autowired
    10. private StringRedisTemplate stringRedisTemplate;
    11. @Test
    12. public void testZSet() {
    13. // ZSetOperations 操作 可以排序的集合类型
    14. ZSetOperations<String, String> zSetOperations = stringRedisTemplate.opsForZSet();
    15. //添加一个值
    16. zSetOperations.add("score", "jack", 60);
    17. Set<ZSetOperations.TypedTuple<String>> set = new HashSet<>();
    18. //添加多个值
    19. DefaultTypedTuple<String> typedTupleForJim = new DefaultTypedTuple<>("jim", new Double(80));
    20. DefaultTypedTuple<String> typedTupleForTom = new DefaultTypedTuple<>("tom", new Double(70));
    21. set.add(typedTupleForJim);
    22. set.add(typedTupleForTom);
    23. zSetOperations.add("score", set);
    24. //获取值
    25. Set<ZSetOperations.TypedTuple<String>> score = zSetOperations.rangeWithScores("score", 0, -1);
    26. System.out.println(score);
    27. //遍历
    28. //for (ZSetOperations.TypedTuple<String> stringTypedTuple : score) {
    29. // System.out.println(stringTypedTuple);
    30. //}
    31. }
    32. }

    10.3.2RedisTemplate

    处理对象相关操作

    10.3.2.1redisTemplate默认如果保存对象,使用jdk序列化机制

    实体类User

    1. package com.tjetc.entity;
    2. import java.io.Serializable;
    3. /**
    4. * 自定义实体类,目的是要序列化到redis中
    5. */
    6. public class User implements Serializable {
    7. private Long id;
    8. private String username;
    9. private String password;
    10. public Long getId() {
    11. return id;
    12. }
    13. public void setId(Long id) {
    14. this.id = id;
    15. }
    16. public String getUsername() {
    17. return username;
    18. }
    19. public void setUsername(String username) {
    20. this.username = username;
    21. }
    22. public String getPassword() {
    23. return password;
    24. }
    25. public void setPassword(String password) {
    26. this.password = password;
    27. }
    28. @Override
    29. public String toString() {
    30. return "User{" +
    31. "id=" + id +
    32. ", username='" + username + '\'' +
    33. ", password='" + password + '\'' +
    34. '}';
    35. }
    36. }

    UserService伪代码(不在本案例中)

    1. package com.tjetc.service;
    2. import org.springframework.beans.factory.annotation.Autowired;
    3. import org.springframework.data.redis.core.StringRedisTemplate;
    4. import org.springframework.data.redis.core.ValueOperations;
    5. import org.springframework.stereotype.Service;
    6. import java.util.List;
    7. @Service
    8. public class UserService {
    9. @Autowired
    10. private StringRedisTemplate stringRedisTemplate;
    11. public List<String> find() {
    12. //从redis中查询
    13. ValueOperations<String, String> valueOperations = stringRedisTemplate.opsForValue();
    14. String value = valueOperations.get("k1");
    15. if (value == null) {
    16. //调用dao,从数据库查询
    17. //存储到redis一份数据
    18. valueOperations.set("k1", "v1");
    19. //组装数据,返回
    20. return null;
    21. } else {
    22. //组装数据,返回数据value
    23. return null;
    24. }
    25. }
    26. }

    RedisTemplateTest

    1. package com.tjetc;
    2. import com.tjetc.entity.User;
    3. import org.junit.jupiter.api.Test;
    4. import org.springframework.beans.factory.annotation.Autowired;
    5. import org.springframework.boot.test.context.SpringBootTest;
    6. import org.springframework.data.redis.core.RedisTemplate;
    7. import org.springframework.data.redis.core.ValueOperations;
    8. @SpringBootTest
    9. public class RedisTemplateTest {
    10. @Autowired
    11. private RedisTemplate redisTemplate;
    12. @Test
    13. public void test() {
    14. //创建一个user对象
    15. User user = new User();
    16. user.setId(1L);
    17. user.setUsername("wangxiao");
    18. user.setPassword("8595105");
    19. ValueOperations valueOperations = redisTemplate.opsForValue();
    20. //对象序列化二进制数据后存储到redis中
    21. valueOperations.set("u", user);
    22. //获取user
    23. User u = (User) valueOperations.get("u");
    24. System.out.println("user=" + u);
    25. }
    26. }


    10.3.2.2改变jdk的序列化规则  (RedisConfiguration)

    ①在配置类中配置自定义序列化规则

    1. package com.tjetc.config;
    2. import org.springframework.context.annotation.Bean;
    3. import org.springframework.context.annotation.Configuration;
    4. import org.springframework.data.redis.connection.RedisConnectionFactory;
    5. import org.springframework.data.redis.core.RedisTemplate;
    6. import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
    7. import org.springframework.data.redis.serializer.StringRedisSerializer;
    8. @Configuration
    9. public class RedisConfiguration {
    10. @Bean
    11. public RedisTemplate userRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
    12. //创建RedisTemplate对象
    13. RedisTemplate<String, Object> template = new RedisTemplate<>();
    14. //设置连接工厂
    15. template.setConnectionFactory(redisConnectionFactory);
    16. //创建Jackson2JacksonRedisSerializer对象,使用Jackson把对象转换json字符串,设置序列化方式
    17. GenericJackson2JsonRedisSerializer serializer = new GenericJackson2JsonRedisSerializer(String.valueOf(Object.class));
    18. //template对象设置value的序列化方式,设置默认序列化
    19. template.setDefaultSerializer(serializer);
    20. //template对象,设置key的序列化方式
    21. template.setKeySerializer(new StringRedisSerializer());
    22. return template;
    23. }
    24. }

    ②使用

    1. package com.tjetc;
    2. import com.tjetc.entity.User;
    3. import org.junit.jupiter.api.Test;
    4. import org.springframework.beans.factory.annotation.Autowired;
    5. import org.springframework.boot.test.context.SpringBootTest;
    6. import org.springframework.data.redis.core.RedisTemplate;
    7. import org.springframework.data.redis.core.ValueOperations;
    8. @SpringBootTest
    9. public class RedisTemplateTest {
    10. @Autowired
    11. private RedisTemplate<String,User> redisTemplate;
    12. @Test
    13. public void test1() {
    14. //创建一个user对象
    15. User user = new User();
    16. user.setId(1L);
    17. user.setUsername("wangxiao");
    18. user.setPassword("8595105");
    19. //对象序列化二进制数据后存储到redis中
    20. ValueOperations<String,User> valueOperations = redisTemplate.opsForValue();
    21. valueOperations.set("u1", user);
    22. //获取user
    23. User u1 = valueOperations.get("u1");
    24. System.out.println("user=" + u1);
    25. }
    26. }

    11、持久化

    11.1Redis持久化概述

    持久化的功能:Redis是内存数据库,数据都是存储在内存中,为了避免进程退出导致数据的永久丢失,需要定期将Redis中的数据以某种形式(数据或命令)从内存保存到硬盘;当下次Redis重启时,利用持久化文件实现数据恢复。除此之外,为了进行灾难备份,可以将持久化文件拷贝到一个远程位置。
    Redis持久化分为RDB持久化和AOF持久化:前者将当前数据保存到硬盘,后者则是将每次执行的写命令保存到硬盘(类似于MySQL的binlog);由于AOF持久化的实时性更好,即当进程意外退出时丢失的数据更少,因此AOF是目前主流的持久化方式,不过RDB持久化仍然有其用武之地。
    下面依次介绍RDB持久化和AOF持久化;由于Redis各个版本之间存在差异,如无特殊说明,以Redis3.0为准。

    11.2RDB持久化

    默认方式,不需要进行配置,默认就使用这种机制。
    在一定的间隔时间中,检测key的变化情况,然后持久化数据

    1.编辑redis.windows.conf配置文件

     

     #   after 900 sec (15 min) if at least 1 key changed
    save 900 1
    #   after 300 sec (5 min) if at least 10 keys changed
    save 300 10
    #   after 60 sec if at least 10000 keys changed
    save 60  10000
    如果我们将配置该成如下形式:
    save 900 1
    save 300 10
    save 20  5        在20秒之后,如果有5个键发生了改变,则执行持久化

    2.重启服务器,并指定配置文件

    3.启动客户端

     

    上述操作在20秒内完成。这时在当前目录下会出现一个rdb文件。


    关闭服务器和客户端。

    4.重新启动服务器和客户端,不需要指定配置文件。

    在客户端直接获取username,结果如下:

    11.3AOF持久化

    日志记录的方式,可以记录每一条命令的操作。可以每一次命令操作后,持久化数据。

    1.编辑redis.windows.conf配置文件

       aof持久化文件名称

     appendonly no(关闭aof) --> appendonly yes (开启aof)
     AOF相关配置:
    # appendfsync always   每一次操作都进行持久化
    appendfsync everysec   每一秒进行一次持久化,默认方式
    # appendfsync no          不进行持久化

    2.重启服务器,指定配置文件

    3.启动客户端,1秒持久化一次

    127.0.0.1:6379> set username lisi
    OK
    127.0.0.1:6379> set password 123
    OK

    4.关闭并重启服务器(指定配置文件)和客户端,在客户端获取,结果如下:

    127.0.0.1:6379> keys *
    1) "password"
    2) "username"
    127.0.0.1:6379> get username
    "lisi"
    127.0.0.1:6379> get password
    "123"

    Redis为什么这么快?

    1、完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。数据存在内存中,类似于 HashMap,HashMap 的优势就是查找和操作的时间复杂度都是O(1);
    2、数据结构简单,对数据操作也简单,Redis 中的数据结构是专门进行设计的;
    3、采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;
    4、使用多路 I/O 复用模型,非阻塞 IO;
    5、使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis 直接自己构建了 VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求。

  • 相关阅读:
    三十分钟学会Hive
    AWS】在EC2上创建root用户,并使用root用户登录
    GhatGPT AIGC 人工智能数据分析与可视化Python
    第七天项目实战二
    【Redux 和 React-Recux】
    魅族回应被吉利收购:已签署协议;腾讯下架QQ影音所有版本;PyPI多个软件包因拼写错误包含后门|极客头条
    最佳实践:DevOps在嵌入式软件开发领域的实践探索丨IDCF
    解析DNA甲基化临床科研 | 无论什么科室,一定要有project的经典视角|易基因
    有重复元素的快速排序
    什么是阿里云8核16G服务器ecs.c6.2xlarge?
  • 原文地址:https://blog.csdn.net/weixin_45701868/article/details/125524670