一、Redis

一、Redis介绍

1.1 锋迷商域项目的问题

  • 数据库访问压力:为了降低对数据库的访问压力,当多个用户请求相同的数据时,我们可以将第一次从数据库查询到的数据进行缓存(存储到内存中),以减少对数据库的访问次数
  • 首页数据的加载效率:将大量的且不经常改变的数据缓存在内存中,可以大幅度提高访问速度
  • 集群部署下的商品超卖

1.2 Redis介绍

1.2.1 Redis的产生背景

  • 2008年 萨尔瓦多–开发一个进行网站实时统计软件项目(LLOOGG),项目的实时统计功能需要频繁的进行数据库的读写,MySQL满足不了项目的需求,萨尔瓦多就是使用C语言自定义了一个数据存储系统—Redis。后来萨尔瓦多不满足LLOOGG这个项目中使用redis,就对redis进行产品化并进行开源,以让更多的人能够使用

1.2.2 Redis 使用

Redis就是一个C语言开发的、基于内存结构进行的键值对数据存储的、高性能的、非关系型NoSQL数据库。

1.2.3 Redis支持的数据类型

redis是基于键值对进行数据存储的,但是value可以是多种数据类型

  • 字符串
  • hash 映射
  • List 列表(队列)
  • set 集合
  • Zset 无序列表

Redis特点

  • 基于内存存储,数据读写效率高
  • Redis本身支持持久化
  • Redis虽然基于key-value存储,但是支持多种数据类型
  • Redis支持集群、支持主从模式

1.3 Redis应用场景

  • 缓存:在绝大多数的互联网项目中,为了提供数据的访问速度、降低数据库的访问压力,我们可以使用redis作为缓存来实现
  • 点赞、排行榜、计数器等功能:对数据实时读写要求比较高,但是对数据库的一致性要求并不是很高
  • 分布式锁:基于redis的操作特性可以实现分布式锁功能
  • 分布式会话:在分布式系统中可以使用redis实现session(共享缓存)
  • 消息中间件:可以使用redis实现应用之间的通信

1.4 Redis的优缺点

1.4.1 优点

  • redis是基于内存结构,性能极高(读110000次/秒,写81000次/秒)
  • redis基于键值对存储,但是支持多种数据类型
  • redis的所有操作都是原子性,可以通过lua脚本将多个操作合并为一个原子操作(redis的事务)
  • redis是基于单线程操作,但是其多路复用实现了高性能读写

1.4.2 缺点

  • 缓存数据与数据库数据必须通过两次写操作才能保持数据的一致性
  • 使用缓存会存在缓存穿透、缓存击穿、缓存雪崩等问题,需要处理
  • redis可以作为数据使用进行数据的持久存储,存在丢失数据的风险

二、Redis安装及配置

2.1 Redis安装

基于linux环境安装redis

2.1.1 下载redis

wget http://download.redis.io/releases/redis-5.0.5.tar.gz

2.1.2 安装redis

  • 安装gcc
yum -y install gcc
  • 解压redis安装包
tar -zxvf redis-5.0.5.tar.gz
  • 解压之后进入到redis-5.0.5目录
cd redis-5.0.5
  • 编译
make MALLOC=libc
  • 安装
make install

##当我们安装redis之后,就可以执行redis相关指令
## redis-server 启动redis服务
## redis-cli 启动redis操作客户端(命令行客户端)
  • 启动redis
##当我们安装redis之后,就可以执行redis相关指令
redis-server  ## 启动redis服务
redis-server &  ##后台启动
  • 打开客户端
redis-cli   ##启动redis操作客户端(命令行客户端)

2.2 Redis 配置

  • 使用 redis-server 指令启动redis服务的时候,可以在指令后添加redis配置文件的路径,以设置redis是以何种配置进行启动
redis-server redis.conf &   ##redis以redis.conf  文件中的配置来启动
  • 如果不指定配置文件的名字,则按照redis的默认配置启动(默认≠redis.conf)
  • 我们可以通过创建redis根目录下的redis.conf来创建多个配置文件启动多个redis服务
##这里启动两个redis服务,端口不一样
redis-server redis-6381.conf & 

redis-server redis-6382.conf &
##设置redis实列是否为守护模式,默认值为no
daemonize no|yes 

##设置当前redis实列启动之后保存进程id的文件路径
pidfile /var/run/redis.pid

## 设置redis实列的启动端口(默认为6379)
port 6380

## 设置当前redis实列是否开启保护模式
protected-mode yes

## 设置允许当前redis实列的ip地址访问列表
bind 127.0.0.1

## 设置连接密码
requirepass 123456

## 设置redis实列中数据库的个数(默认16个,编号0--15)
databases 16

## 设置最大并发数
maxclients 1000

##设置客户端和 redis 建立连接的最大空闲时间,设置为0表示不限制
timeout 0

## 查看所有运行的redis服务
ps -aux|grep redis

## 查看某个运行的redis服务
lsof -i:端口

三、Redis基本使用

3.1 Redis存储的数据结构

Redis是以键值对形式进行数据存储的,但是value支持多种数据类型

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TydjOfTk-1662558885745)(/Users/gen_hua/Desktop/Java_note/Markdown/WechatIMG939.jpeg)]

3.2 string常用命令

## set 设置值/修改值。如果存在就修改,不存在就创建
set key1 value1

##取值
get key1

## 批量添加
mset key2 value2 key3 value3 key4 value4.....

## 批量取值
mget key2 key3 key4....

## 自增和自减
incr key   ## 在key对应的value值上自增1  即 +1
decr key   ## 在key对应的value值上自减1  即 -1
incrby key v  ##在key对应的value上加 v
decrby key v  ##在key对应的value上减 v

## 添加键值对,并设置过期时间
setnx key time(seconds) value

##设置值,如果key不存在则成功添加,如果key存在则添加失败(不做修改操作)
setnx key value

## 在指定的key对应value拼接字符串
append key value

## 获取key对应的字符串的长度
strlen key

3.3 hash常用命令

## 向key对应的hash中添加键值对
hset key field value

## 从key对应的哈希中获取field对应的值
hget key field

## 向key对应的hash结构中批量添加键值对
hmset key field value1 value2 value3....

## 从key对应的hash中批量获取值
hmget key field1 field2 field3......

## 自增  在对应的hash中的field中对应的value加v
hincrby key field v

## 获取key对应的hash中所有的field
hgetall key

## 获取key对应的hash中所有的value
hkeys key

## 获取key对应的hash中键值对的个数
hlen key


3.4 list常用指令

## 存储数据
lpush key value   ## 在key对应的列表的左侧添加数据value
rpush key value   ## 在key对应的列表的右侧添加数据value

## 获取数据
lpop key  ## 从key对应的列表的左侧取一个值
rpop key  ## 从key对应的列表的右侧取一个值

## 修改数据
lset key index value  ## 修改key对应的列表的索引未知的数据(索引从左网右,从0开始)

## 查看 key 对应的列表中索引从start开始到stop索引
lrange key start stop

## 查看key对应的列表中index索引对应的值
lindex key index

## 获取key对应的列表中的元素个数
llen key

## 从key列表中截取key在start,stop范围的值,不在此范围的值,一律被清除掉
ltrim key start stop

## 从k1右侧取出一个数据,然后存放到k2的左侧
rpoplpush k1 k2

3.5 set常用指令

## 存储元素  在key对应的集合中添加元素,可以添加1个,也可以同时添加多个元素
sadd  key value1 value2 value3.....

## 遍历key对应的集合中的所有元素
smembers key

## 从key对应的结合中移除value,如果不存在则不移除
srem key value

## 查看 key对应的集合 中是否有value
sismember key value

四、Redis的持久化

redis是基于内存操作中,单作为一个数据库也具备数据的持久化能力,但是为了实现高效的读写操作,并不会即时进行数据的持久化,而是按照一定的规则进行持久化操作的 --这种规则叫做持久化策略

Redis提供了2种持久化策略

  • RDB(Redis DataBase)
  • AOF(Append Only File)

RDB

在满足特定的redis操作条件时,将内存中的数据以数据快照的形式存储到rdb文件中

  • 原理:
    • RDB是Redis默认的持久化策略,当redis中的写操作达到指定次数及时间周期,同时距离上一次持久化达到指令的时间就会将redis内存中数据生成快照,保存在指定的RDB文件中。
  • 默认触发持久化条件:
    • 900秒 1次:当操作次数达到1次,900秒就会进行持久化
    • 300秒 10次:当操作次数达到10次,300秒就会进行持久化
    • 60秒 1000次:当操作次数达到1000次,60秒就会进行持久化
  • 我们可以通过修改redis.conf文件,来设置RDB策略的触发条件
## rdb持久化开关
rdbcompression yes

## 配置redis的持久化策略
save 900 1
save 300 10
save 60 10000

## 指定rdb数据存储的文件
dbfilename dump.rdb
  • RDB持久化细节分析

    缺点

    • 如果redis出现故障,存在数据丢失的风险,丢失上一次持久化之后的操作数据
    • RDB采用的是数据快照心事进行持久化,不适合实时性持久化;但是在数据较小的情况下,执行速度比较快
    • 如果数据巨大,在RDB持久化过程中,生在数据库快照的子进程执行时间过长,会导致redis卡顿,因此save时间周期设置不宜过短

    优点

    • 但是在数据量较小的情况下,执行的速度比较快
    • 由于EDB是以数据快照的形式进行保存的,我们可以拷贝rdb文件轻松实现redis数据移植

4.2 AOF

Apeend Only File,当达到设定触发条件时,将rdis执行的写操作指令存储在aof文件中,Redis默认未开启aof持久化

  • 原理:
    • Redis将每一个成功的写操作写入到aof文件中,当redis重启的时候就执行ao文件中的指令以恢复数据
  • 配置:
## 开启AOF
appendonly yes

## 设置触发条件(三选一)
appendfsync always    ## 只要进行成功的写操作就执行aof
appendfsync everysec  ## 美妙进行一次aof
appendfsync no   ## 让redis仔细决定

## 设置aof文件路径
appendfilename "appendonly.aof"
  • AOF细节分析:
    • AOF文件也可以通过拷贝aof文件进行redis数据的移植
    • aof存储的是指令,而且会对指令进行整理,而RDB直接生成数据快照,因此在数据量不大时,RDB比较快
    • aof是对指令文件进行增量更新,更适合实时性持久化
    • redis官方建议同时开启2中持久化策略,如果同时存在aof文件和rdb文件的情况下,aof优先

五、Java应用连接Redis

Java应用连接Redis,首先要将我们的Redis设置允许远程连接

  • 修改redis-6379.conf
## 关闭保护模式
protected-mode no

## 将bind注释(如果注释,默认为 127.0.0.1 只能本机访问)
bind 127.0.0.1   ## 将这行注释掉

## 设置密码  (可设置可不设置,不设置的话直接注释就可以)
requirepass 199610fan
  • 重启redis
redis-server redis-6379.conf
  • 云服务器中安全组设置6379端口

5.1 在普通Maven工程连接Redis

5.1.1 添加Jedis依赖

<dependency>
  <groupId>redis.clients</groupId>
  <artifactId>jedis</artifactId>
  <version>2.9.0</version>
</dependency>

<dependency>
  <groupId>com.google.code.gson</groupId>
  <artifactId>gson</artifactId>
  <version>2.8.5</version>
</dependency>

5.1.2 使用案列

  • Product类
package com.luo.beans;

public class Product {
    private String productId;
    private String productName;
    private Double productPrice;

    @Override
    public String toString() {
        return "Product{" +
                "productId='" + productId + '\'' +
                ", productName='" + productName + '\'' +
                ", productPrice=" + productPrice +
                '}';
    }

    public Product(String productId, String productName, Double productPrice) {
        this.productId = productId;
        this.productName = productName;
        this.productPrice = productPrice;
    }

    public Product() {
    }

    public String getProductId() {
        return productId;
    }

    public void setProductId(String productId) {
        this.productId = productId;
    }

    public String getProductName() {
        return productName;
    }

    public void setProductName(String productName) {
        this.productName = productName;
    }

    public Double getProductPrice() {
        return productPrice;
    }

    public void setProductPrice(Double productPrice) {
        this.productPrice = productPrice;
    }
}

  • 主类
public class RedistTest {
  public static void main(String[] args) {

    Product product = new Product("101","娃哈哈AD钙奶",2.5);

    //1、连接redis
    Jedis jedis = new Jedis("114.116.13.83", 1122);

    String set = jedis.set(product.getProductId(), new Gson().toJson(product));

    System.out.println(set);

    jedis.close();
  }

5.2 在SpringBoot工程中连接Redis

5.2.1 创建SpringBoot应用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AvzugFiZ-1662558885746)(/Users/gen_hua/Desktop/Java_note/Markdown/WX20220820-111018@2x.png)]

5.2.2 配置rdis

Application.yml文件配置redis的连接信息

spring:
  redis:
    host: 114.116.13.83
    port: 1122
    database: 0

5.2.3 使用reids客户端连接reids

直接在service中注入 redisTemplate或者stringRedisTemplate,就可以使用此对象完成redis操作

5.3 Spring Data Redis

5.3.1 不同数据结构的添加操作

package com.example.redisboot.service.impl;

@Service
public class ProductServiceImpl implements ProductService {


    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

  	 /**
     * 从redis中存数据
     */
    @Override
    public void addInfoToRedis() {

        try {
            Product product = new Product("103", "王老吉", 3.4);
            String jsonstr = new ObjectMapper().writeValueAsString(product);
            //stringRedisTemplate.boundValueOps(product.getProductId()).set(jsonstr);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }

    /**
     * 从redis中取数据
     */
    @Override
    public Product getInfoFromRedis(String productId) {

        Product product = null;
        try {
            String s = stringRedisTemplate.boundValueOps(productId).get();

            if (s != null){
                product = new ObjectMapper().readValue(s,Product.class);
            }
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }

        return product;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值