Redis 安装-启动

  • gz 压缩包安装

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    # 可以直接写入脚本文件中一次执行

    # 安装依赖、安装 gcc: c/c++ 编译器
    yum install -y gcc tcl gcc-c++
    # 指定安装位置问题: 解压的 tar 文件的放置位置就是安装路径,配置文件等全在此处

    # 下载 redis gz 镜像地址 选择所需版本
    https://mirrors.huaweicloud.com/redis/
    # 下载 6.2.4
    wget https://mirrors.huaweicloud.com/redis/redis-6.2.4.tar.gz
    # 解压
    tar -zxvf redis-6.2.4.tar.gz
    # 进入目录
    cd redis-6.2.4.tar.gz

    # 编译
    make
    # 如果 make出错,则执行如下(执行清理命令),之后再次执行 make
    make distclean
    # 在 make 执行后再执行 make install 该操作则将 src 下的许多可执行文件复制到 /usr/local/bin 目录下,这样做可以在任意目录执行 redis 的软件命令(例如: 启动、停止、客户端连接服务器等)
    make install
  • make install

    make-install 执行作用(默认的安装路径)
    make-install执行作用
  • 前台启动不推荐,占用整个控制台

    前台启动(redis-server)
    前台启动
    • 后台启动redis 服务

      1
      2
      # 备份 redis.conf(解压后的目录中)
      cp redis.conf redis.conf.default
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      # 修改配置
      # 允许访问的地址,默认是 127.0.0.1 会导致只能在本地访问,修改为 0.0.0.0则可以在任意 IP 访问,生产环境下要设置为 0.0.0.0
      bind 0.0.0.0
      # 守护进程,修改为 yes 后即可后台运行
      daemonize yes
      # 默认是yes,即开启。当配置为 no,此时外部网络可以直接访问
      protected-mode no

      # 密码 设置后访问 Redis 必须输入密码
      # requirepass root

      • 启动方式

        1
        2
        # 后台启动,在任何目录下执行,未修改配置文件时,将以默认配置启动
        redis-server &
        1
        2
        3
        4
        5
        6
        7
        8
        9
        # 启动 redis 服务时指定配置文件(修改配置文件时,在解压目录中执行)
        redis-server redis.conf &

        # 查看启动是否成功(获取进程 pid)
        ps -ef|grep redis

        # 安装 lsof
        yum -y install lsof
        lsof -i:6379
    • 关闭redis 服务

      1
      2
      3
      4
      5
      6
      7
      # 1. 关闭对应进程(数据有丢失风险) 获取进程 pid
      ps -ef|grep redis
      kill -9 pid

      # 2. 使用 redis 命令关闭(推荐)
      redis-cli shutdown

      redis-命令关闭
      redis-命令关闭
    • redis 客户端

      redis 客户端: 用来连接redis 服务,redis 服务端发送命令,并且显示redis 服务处理结果

      redis-cli: 是redis 自带客户端,使用命令redis-cli 就可以启动redis 的客户端程序

      redis-cli:默认连接127.0.0.1:6379 redis 服务

      redis-cli -p 指定端口号连接

      redis -[p -h ip地址连接指定ip 主机上的指定端口的redis 服务

    • 退出客户端

      1
      exit
      redis-启动-退出
      redis-启动-退出
  • 如果某些命令不想被其他人使用,则可以通过配置文件中的rename-command 进行修改

    1
    2
    rename-command flushall ""
    rename-command flushdb ""

开机自启

  • 配置: 首先,新建一个系统服务文件

    1
    vim /etc/systemd/system/redis.service
  • 填入如下内容

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    [Unit]
    Description=redis-server
    After=network.target

    [Service]
    Type=forking
    ExecStart=/usr/local/bin/redis-server /root/redis-6.2.4/redis.conf
    PrivateTmp=true

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

    1
    systemctl daemon-reload
  • 可以用下面这组命令来操作redis

    1
    2
    3
    4
    5
    6
    7
    8
    # 启动
    systemctl start redis
    # 停止
    systemctl stop redis
    # 重启
    systemctl restart redis
    # 查看状态
    systemctl status redis
  • 开机自启

    1
    systemctl enable redis
  • 后续连接方式

    前提条件: 服务已处于启动状态
    1
    2
    3
    4
    5
    6
    7
    # 当 redis 服务为启动状态时,只需要通过如下命令进入 redis 控制台即可
    # 方式一: 使用服务端配置直接启动
    redis-cli

    # 方式二: 可以启动指定,也可以是本机的服务
    redis-cli -h 192.168.2.3 -a password

基本知识

  1. 测试redis 服务的性能

    1
    redis-benchmark
  2. 查看redis 服务是否正常运行

    1
    ping 如果正常 ==> pong
  3. 查看redis 服务器的统计信息

    1
    2
    3
    4
    # 查看 redis 服务的所有统计信息
    info
    # 查看 redis 服务器的指定的统计信息 # CPU | # Replication | ...
    info [信息段]
  4. redis 数据库实例

    • 了解

      redis 中的数据库实例只能由redis 服务来创建和维护,开发人员不能修改和自行创建数据库实例,默认情况下,redis 会自动创建16 个数据库实例,并且会给这些数据库实例进行编号,0 开始,一直到15,使用时通过编号来使用数据库,可以通过配置文件,指定redis 自动创建的数据库个数,redis 的每一个数据库实例本身占用的存储空间是很少的,所以也不造成存储空间的太多浪费,默认情况下,redis 客户端连接的是编号是0 的数据库实例

    • 数据库切换

      1
      select index
    • 查看当前数据库实例中所有key 的数量

      1
      dbsize
    • 查看当前数据库实例中所有的key

      1
      keys *
      基础使用
      基础使用
    • 清空数据库实例

      1
      2
      3
      flushdb
      # 慎重使用 清空所有数据库实例
      flushall
    • 查看redis 配置信息

      1
      2
      3
      4
      # 查看所有配置信息
      config get *
      # 查看指定字段
      config get port

Redis卸载

  • 输入以下命令查看reids 是否在运行,如果在运行需要将其关闭。

    1
    2
    3
    ps aux | grep redis #查看reids是否在运行

    kill -9 PID #通过杀掉reids进程将其关闭
  • 停止服务

    1
    redis-cli shutdown
  • 删除相关目录

    1
    2
    3
    rm -rf /usr/local/bin/redis-* #删除redis文件

    ls /usr/local/bin/redis-* #查看redis文件
  • 删除解压文件

    1
    rm -rf redis-*

客户端界面下载

Redis 常用命令

keys操作命令

  • keys: 查看符合模板的所有key, 不建议在生产环境设备上使用,是因为在一个大的数据库中使用他可能会阻塞当前服务器的服务,在生产环境中,可以使用 scan 命令代替

    1. keys * 匹配0 个或者多个字符
    2. keys ? 匹配一个字符
    3. keys [] 匹配[] 里边的1 个字符
    keys
    keys
  • 判断key 在数据库中是否存在

    1
    2
    # 如果存在返回 1,不存在 返回 0
    exists key
    exists
    exists
  • 移动指定key 到指定的数据库实例

    1
    move key index
    move
    move
  • 查看指定key 的剩余生存时间

    1
    2
    3
    4
    5
    ttl: time to live
    # 语法
    ttl key
    # 如果 key 没有设置生存时间,返回 -1
    # 如果 key 不存在,返回 -2
  • 设置key 的最大生存时间

    1
    expire key seconds[秒]
    ttl
    ttl
  • 查看指定key 的数据类型

    1
    type key
  • 重命名

    1
    rename key newkey
  • 删除指定的key

    1
    2
    # 返回值是实际删除的 key 的数量
    del key1 key2 ...
    del
    del
  • persist

    • 格式: persist key
    • 功能: 去除给定key 的生存时间,将这个key 易失的转换为持久的
    • 说明: 当生存时间移除成功时,返回: 1,若key 不存在或key 没有设置生存时间,则返回0
  • randomkey

    • 格式: randomkey
    • 功能: 从当前数据库中随机返回(不删除)一个key
    • 说明: 当数据库不为空是,返回一个key。当数据库为空时,返回nil
  • scan

    • hscan: Hash
    • sscan: Set
    • zscan:ZSet

Redis数据结构介绍

  • 是什么

    Redis 是一个key-value 的数据库,key 一般是string 类型,不过value 的类型是多种多样的

  • 数据类型

    数据类型

数据类型操作

String

  • String 类型,也就是字符串类型,Redis 中最简单的存储类型,value 是字符串,不过根据字符串的格式不同,又可以分为3

    • String: 普通字符串
    • int: 整数类型,可以做自增、自减操作
    • float: 浮点类型,可以做自增、自减操作
  • String 类型的数据设置到redis

    1
    2
    # set 键 值(key 存在则更新)
    set username coder-itl
  • redis 中获取string 类型的数据

    1
    get username
  • 追加字符串

    1
    2
    # 返回追加之后的字符串长度 如果 key 不存在,则新创建一个 key 并且把 value 值设置为 value
    append key value
  • 获取字符串数据的长度

    1
    strlen username
    string
    string
  • 字符串数值+1 /-1 运算

    1
    2
    3
    4
    5
    6
    7
    8
    # 返回加 1  运算之后的数据 如果 key 不存在,首先设置一个 key 值初始化为 0 然后进行 incr 运算
    incr key

    # 返回减 1 运算之后的数据 如果 key 不存在,首先设置一个 key 值初始化为 0 然后进行 incr 运算
    decr key

    # 必须是数值类型

    incr-decr
    incr-decr
  • 带偏移量的+/-

    1
    2
    3
    # 将字符串数值进行 offset 运算
    incrby key offset
    decrby key offset
    incrby-decrby
    incrby-decrby
  • 子串

    1
    2
    # 获取字符串 key 中 startIndex 的字符串组成的子字符串(下标自左至右,从 0 开始,最后一个字符的下标是字符串长度-1,属于[](数学含义),而不是 ( ]  )
    getrange key starIndex endIndex
  • 覆盖

    1
    2
    # 用 value 覆盖从下标 startIndex 开始的字符串,其余位数保留或新增
    setrange key startIndex value
    覆盖
    覆盖
  • 设置字符串数据的同时,设置它的最大生命周期

    1
    2
    3
    4
    5
    6
    # 存在也会设置
    setex key seconds value

    # key 不存在时设置,否则放弃设置
    setnx key value

  • 批量设置key redis 数据库中

    1
    2
    3
    4
    5
    6
    7
    # 批量设置
    mset key1 value1 key2 value2 ...
    # 批量获取
    mget key1 key2 ...
    # 只要一个存在则放弃
    msetnx

    mset
    mset

List

  • Redis 中的List 类型与Java 中的LinkedKist 类似,可以看作是一个双向链表结构。既可以支持正向检索和也可以支持反向检索

    • 特征

      • 有序
      • 元素可以重复
      • 插入和删除快
      • 查询速度一般
    • 分析

      A 为起始,如果执行LPUSH C,结果出现在A 的左侧,E 进行RPUSH 出现在右侧
  • lpush

    1
    2
    3
    4
    5
    6
    7
    # 元素在列表中的顺序或者下标由放入的顺序来决定
    # 删除列表
    del key
    # 将一个或者多个值依次插入到列表的表头(左侧)
    lpush key value1 value2 ....
    # 查看列表中的数据
    lrange key startIndex endIndex
    将一个或者多个值依次插入到列表的表头(左侧) 分析
    lpush
  • rpush

    1
    2
    # 将一个或者多个值依次插入到列表的表尾
    rpush key value
    将一个或者多个值依次插入到列表的表尾
    rpush
  • lpop

    1
    2
    # 从指定列表中移除并且返回表头元素
    lpop key
    lpop 从指定列表中移除并且返回表头元素
    lpop
  • rpop

    1
    2
    # 从指定列表中移除并且返回表尾元素
    rpop key
  • lindex

    1
    2
    # 获取列表中指定下标的元素
    lindex key
    lindex
    lindex
  • 获取指定列表的长度

    1
    llen key
  • lrem

    1
    2
    3
    4
    5
    # 根据 count 值移除指定列表中跟 value 相等的数据
    lrem key count value
    # count > 0 从列表的左侧移除 count 个和 value 相等的数据
    # count < 0 从列表的右侧移除 count 个和 value 相等的数据
    # count = 0 从列表移除 count 个和 value 相等的数据
    lrem
    lrem

Set

  • Redis Set 结构与Java 中的HashSet 类似,可以看作是一个value null HashMap。因为也是一个hash 表,因此具备与HashSet 类似的特征

    • 特征
      • 无序
      • 元素不可重复
      • 查找快
      • 支持交集、并集、差集等功能
  • sadd

    1
    2
    3
    # 将一个或者多个元素添加到指定的集合中
    sadd key value
    # 返回成功加入元素的个数,如果元素存在,则会忽略
  • smembers

    1
    2
    # 获取指定集合中所有的元素
    smembers key
  • sismember

    1
    2
    3
    4
    # 判断指定元素在指定集合中是否存在
    sismember key member
    # 存在 返回 1
    # 不存在 返回 0
  • scard

    1
    2
    # 获取指定集合的长度
    scard key
  • srem

    1
    2
    # 移除指定集合中一个或者多个元素
    srem key member
    set
    set
  • srandmember

    1
    2
    3
    4
    5
    6
    7
    8
    # 随机获取指定集合中的一个元素
    srandmember key

    srandmember key count

    # count > 0 随机获取的多个元素之间不能重复
    # count < 0 随机获取的多个元素之间可能重复

  • spop

    1
    2
    # 从指定集合中随机移除一个或者多个元素
    spop key [count]
  • smove

    1
    2
    # 将指定集合中的指定元素移动到另一个集合中
    smove source desc member
    smove
    smove
  • sdiff(差)

    1
    2
    # 获取第一个集合中有,但是其他集合中都没有的元素组成的新集合
    sdiff key key
  • sinter(交)

    1
    2
    # 获取所有指定集合中都有的元素组成的新集合
    sinter key key
    sinter
    sinter
  • sunion(并)

    1
    2
    # 获取所有指定集合中所有的元素组成的大集合
    sunion key key
    sunion
    sunion
  • 案例练习

    • 将下列数据用Redis Set 集合来存储

      • 张三的好友有: 李四、王五、赵六

        1
        sadd zhangsan 李四 王五 赵六
      • 李四的好友有: 王五、麻子、二狗

        1
        sadd lisi 王五 麻子 二狗
        张四的好友有
    • 利用Set 的命令实现下列功能

      • 计算张三的好友有几人

        1
        scard zhangsan
      • 计算张三和李四有那些共同好友

        集合 交集
        1
        2
        # 交集
        sinter zhangsan lisi
      • 查询那些人是张三的还有却不是李四的好友

        1
        2
        # 差集
        sdiff zhangsan lisi
      • 查询张三和李四的好友总共有那些人

        1
        2
        # 并集
        sunion zhangsan lisi
      • 判断李四是否是张三的好友

        1
        sismember zhangsan lisi
      • 判断张三是否是李四的好友

        1
        2
        # 判断李四在不在张三的列表中
        sismember lisi zhangsan
      • 将李四从张三的好友列表中移除

        1
        srem zhangsan lisi

Hash

  • Hash 类型,也叫散列,其value 是一个无序字典,类似于Java 中的HashMap 结构

    • String 结构是将对象结果序列化为JSON 字符串后存储,当需要修改对象某个字段时很不方便

      对象结果序列化为JSON 字符串后存储
    • Hash 结构可以将对象中的每个字段独立的存储,可以针对单个字段做CRUD

  • hset

    1
    2
    3
    4
    5
    6
    # 将一个或者多个 field-value 对设置到哈希表中
    hset key field ...

    # hash 存储
    hset vue:admin:userinfo name Jack
    hset vue:admin:userinfo age 18
    hset
  • hget

    1
    2
    # 获取指定哈希表中指定 field 的值
    hget key field
  • hmset

    1
    2
    # 批量将多个 field-value 对设置到哈希表中
    hmset key field1 field2 ...
  • hmget

    1
    2
    # 批量获取多个 field-value 的值
    hmget key field1 field2 ...
  • hgetall

    1
    2
    # 获取指定哈希表中所有的 field 和 value 
    hgetall key
  • hdel

    1
    2
    # 从指定哈希表中删除一个或者多个 field
    hdel key field1 field2 ...
  • hlen

    1
    2
    # 获取指定哈希表中所有的 field 个数
    heln key
  • hexists

    1
    2
    # 判断指定哈希表中是否存在某一个 field 
    hexists key field
  • hkeys

    1
    2
    # 获取指定哈希表中所有的 field 列表
    hkeys key
  • hvals

    1
    2
    # 获取指定哈希表中所有的 value 列表
    hvals key
  • hincrby

    1
    2
    3
    4
    5
    # 对指定哈希表中指定 field 值进行整数加法运算 
    hincrby key field int

    # Eg:
    hincrby key field 5
  • hincrbyfloat

    1
    2
    3
    4
    5
    # 对指定哈希表中指定 field 值进行浮点数加法运算
    hincrbyfloat key field float
    # Eg:
    hincrbyfloat stu score 5.5

  • hsetnx

    1
    2
    # 将一个 field-value 对设置到哈希表中,当 key-filed 已经存在时,则放弃设置,否则 设置 filed-value
    hsetnx key field

Zset

  • 简介

    redis 有序集合zset 和集合set 一样也是string 类型元素的集合,且不允许重复的成员

    不同的是zset 的每个元素都会关联一个分数(分数可以重复)redis 通过分数来为集合中的成员进行从小到大的排序

  • Redis SortedSet 是一个可排序的set 集合,与Java 中的TreeSet 有些类似,但是底层数据结构差别很大,SortedSet 中的每一个元素都带有一个score 属性,可以基于score 属性对元素排序,底层的实现是一个跳表加Hash

  • SortedSet 特性

    • 可排序
    • 元素不重复
    • 查询速度快
    • 因为SortedSet 的可排序特性,经常被用来实现排行榜这样的功能
  • zadd

    1
    2
    3
    4
    # 将一个或者多个 member 及其 score 值加入有序集合
    zadd key score member ...
    # Eg: score(键名称)
    zadd score 1 a 2 b 3 c ...
  • zrange

    1
    2
    # 获取指定有序集合中指定区间的元素
    zrange key startIndex endIndex [withscores]
    zadd-zrange
    zadd-zrange
  • zrangebyscore

    1
    2
    3
    4
    # 获取指定有序集合中指定分数区间(闭区间)的元素
    zrangebyscore key scorreStart endScore withscores
    # Eg:
    zrangebyscore score[有序集合名] scorreStart[起始区间] endScore[结束区间] withscores
    zrangebyscore
    zrangebyscore
  • zrem

    1
    2
    # 删除指定有序集合中一个或者多个元素
    zrem key a b
  • zcard

    1
    2
    # 获取指定有序集合中所有元素的个数 
    zcard key
  • zcount

    1
    2
    # 获取指定有序集合中分数在指定区间内的元素的个数
    zcount key 20 50
  • zrank

    1
    2
    3
    4
    # 获取指定有序集合中指定元素的排名(排名从 0 开始)
    zrank key member
    # Eg:
    zrank key a
  • zscore

    1
    2
    3
    4
    # 获取指定有序集合中指定元素的分数
    zscore key member
    # Eg:
    zscore key a
  • zrevrank

    1
    2
    # 获取指定有序集合中指定元素的排名 逆序排名(大 -> 小)
    zrevrank key member
  • zdiff、zinter、zunion:求差集、交集、并集

    注意: 所有的排名默认都是升序、如果要降序则在命令的z 后面添加REV 即可

  • 案例练习

    将班级的学生的粉存入:

    Jack 85,Lucy 89,Rose 82,Tom 95,Jerry 78

    1
    2
    # 添加 student_score(键名) 85 Jack(分数和键)
    zadd student_score 85 Jack 89 Lucy 82 Rose 95 Tom 78 Jerry
    存储后
    • 实现如下

      • 删除Tom 同学

        1
        zrem student_score Tom
      • 获取Rose 同学的分数

        1
        zscore student_score Rose
      • 获取Rose 同学的排名

        1
        2
        3
        4
        # 升序(下标从 0 开始)
        zrank student_score Rose
        # 降序(下标从 0 开始)
        zrevrank student_score Rose
      • 查询80 分以下的有几个学生

        1
        2
        # 统计
        zcount student_score 0 80
      • Jack 同学加2

        1
        zincrby student_score 2 Jack
      • 查出成绩前3 名的同学

        1
        2
        3
        4
        # 升序
        zrange student_score 0 2
        # 倒序
        zrevrange student_score 0 2
        排序
      • 查出成绩80 分以下的所有同学

        1
        2
        # 显示具体信息
        zrangebyscore student_score 0 80

Redis 没有类似 MYSQL 中的 Table 的概念,我们该如何区分不同类型的 Key 呢?

  • 例如: 需要存储用户,商品信息到 Redis,有一个用户id 1,有一个商品id 恰好也是1

  • Key 的结构: Redis key 允许有多个单词形成层级结构,多个单词之间用: 隔开,格式如下

    1
    2
    3
    项目名:业务名:类型:id
    # 验证码: srb(项目名):core(模块):code(验证码相关) 1775297131(手机号) 7g8h(生成的验证码)
    srb:core:code:1775297131 7g8h
    验证码存储
  • 层级结构

    1
    2
    3
    4
    set heima:user:1 '{"id":1,"name":"Jack","age":21}'
    set heima:user:2 '{"id":2,"name":"Rose","age":29}'
    set heima:product:1 '{"id":1,"name":"RedMi","price":4999}'
    set heima:product:2 '{"id":2,"name":"荣耀9","age":2999}'
    层级结构

Redis-配置文件

  • port

    配置端口,默认6379
    配置端口
  • bind

    指定ip
    指定ip

    如果配置了 port bind 则客户端连接redis 服务时,必须指定端口和ip

    redis-cli -h 192.168.10.10 -p 6380
    redis-cli -h 192.168.10.10 -p 6380 shutdown

  • 日志

    日志级别
    日志级别
  • 数据库数量

    数据库数量
    数据库数量

    loglevel: 配置日志级别,开发阶段配置debug,上线阶段配置notice 或者warning

    logfile: 指定日志文件,redis 在运行过程中,会输出一些日志信息,默认情况下,这些日志信息会输出到控制台,我们可以使用logfile 配置日志文件,使用redis 把日志信息输出到指定文件中

    database:配置redis 服务默认创建的数据库实例个数,默认值是16

    logfile
    logfile
  • 安全配置

    1
    2
    3
    requirepass: 设置访问 redis 服务时所使用的密码,默认不使用 此参数必须在 protected-mode=yes 时才起作用
    # 连接方式
    redis-cli -h ip -p port -a pwd

Redis-持久化

简介

  • 简介

    Redis 的持久化:Redis 提供持久化策略,在适当的时机采用适当手段把内存中的数据持久化到磁盘中,每次redis 服务启动时,都可以把磁盘上的数据再次加载到内存中使用

  • RDB 策略

    在指定时间间隔内,redis 服务执行指定次数的写操作,会自动触发一次持久化操作

    RDB 策略是redis 默认的持久化策略,redis 服务开启时这种持久化策略就已经默认开启了

    save <scconds> <changes> 配置持久化策略

    dbfilename 配置redis RDB 持久化数据存储的文件

    dir:配置redis RDB 持久化文件所在目录

  • AOF 策略

    采用操作日志来记录进行每一次写操作,每次redis 服务启动时,都会重新执行一遍操作日志中的指令

    效率低下,redis 默认不开启AOF 功能

    appendonly 配置是否开启AOF 策略

    appendfilename 配置操作日志文件

  • 小结

    一般清空,开启RDB 就足够了

  • 持久化的原理

    持久化原理 持久化文件加载
    在这里插入图片描述

    Redis 持久化也成为钝化,是指将内存中数据库的状态描述信息保存到磁盘中。只不过是不同的持久化技术,对数据的状态描述信息是不同的,生成的持久化文件也是不同的。但是他们的作用都是相同的: 避免数据意外丢失

    通过手动方式,或自动定时方式,或条件自动触发方式,将内存中数据库的状态描述信息写入到指定的持久化文件中。当系统重新启动时,自动加载持久化文件,并根据文件中数据库状态描述信息将数据恢复到内存中,这个数据恢复过程也称为激活.这个钝化与激活的过程就是Redis 持久化的基本原理。

    不过从以上分析可知,对于Redis 单机状态下,无论是手动方式,还是定时方式或条件触发方式,都存在数据丢失问题: 在尚未手动/自动保存时发生了Redis 宕机状况,那么从上次保存到宕机期间产生的数据就会丢失。不同的持久化方式,其数据的丢失率也是不同的。需要注意的是,RDB 是默认的持久化方式,Redis 允许RDN AOF 两种持久化技术同时开启,此时系统会使用AOF 方式做持久化,即AOF 持久化技术优先级要更高。同样的道理,两种技术同时开启状态下,系统启动时若两种持久化文件同时存在,则优先加载AOF 持久化文件

持久化的执行

  • 持久化的执行

    持久化的执行有三种方式: 手动save 命令、手动bgsave 命令、与自动条件触发

    • 查看dump 文件位置

      如果安装根目录下不存在,在进入命令行后可通过该命令获取文件位置config get dir,文件内容不可以直接读取,二进制
    • 手动save

      通过在redis-cli 客户端中执行save 命令可立即进行一次持久化保存。save 命令在执行期间会阻塞 redis-server 进程,直至持久化过程完毕。而在redis-server 进程阻塞期间,Redis 不能处理任何读写请求,无法对外提供服务

    • 手动bgsave 命令

      通过在redis-cli 客户端中执行bgsave 命令可立即进行一次持久化保存。不同于save 命令的是,正如该命令的名称一样,background save,后台运行savebgsave 命令会使服务器进程redis-server 生成一个子进程,由该子进程负责完成保存过程。在子进程保存过程中,不会阻塞redis-server 进程对客户端读写请求的处理

    • 查看持久化时间

      通过lastsave 命令可以查看最近一次执行持久化的时间,其返回值是一个Unix 时间错

RDB-持久化

  • RDB

    RDB,是指将内存中某一时刻的数据快照** 全量 **写入到指定的rdb 文件的持久化技术。RDB 持久化默认是开启的。当Redis 启动时会自动读取``RDB 快照文件,将数据从硬盘载入到内存,以恢复 Redis`关机前的数据库状态。

  • RDB 相关的配置在redis.conf 文件的SNAPSHOTTING 部分

  • RDB 的持久化过程

    RDB-持久化过程流程图

    对于Redis 默认的RDB 持久化,在进行bgsve 持久化时,redis-server 进程会fork 出一个bgsave 子进程,由该子进程以异步方式负责完成持久化。而在持久化过程中,redis-server 进程不会阻塞,其会继续接受并处理用户的读写请求。

    bgsave 子进程的详细工作原理如下:

    ​ 由于子进程可以继承父进程的所有资源,且父进程不能拒绝子进程的继承权。所以,bgsave 子进程由权读取到redis-server 进程写入到内存中的用户数据,是得将内存数据持久化到dump.rdb 成为可能

    bgsave 子进程在持久化时首先会将内存中的全量数据copy 到磁盘中的一个RDB 临时文件,copy 结束后,再将给文件rename dump.rdb,替换掉原来的同名文件。

    不过,再进行持久化过程中,如果redis-server 进程接收到了用户写请求,则系统会将内存中发生数据修改的物理块 copy 出一个副本。等内存中的全量数据copy 结束后,会再将副本的数据copy RDB 临时文件。这个副本的生成是由于Linux 系统的写时复制技术(Copy on Write) 实现的。

AOF-持久化

  • AOF

    AOF(Append Only File): 是指Redis 将每一次的写操作都以日志的形式记录到一个AOF 文件中的持久化技术。当需要恢复内存数据时,将这些写操作重新执行一次,便会恢复到之前的内存数据状态。

  • AOF 基础配置

    • 开启AOF

      1
      2
      3
      appendonly yes
      # redis7 配置文件
      https://github.com/CN-annotation-team/redis7.0-chinese-annotated/blob/7.0-cn-annotated/redis.conf
      redis-6 redis-7
      在这里插入图片描述
  • Rewrite 机制

    随着使用时间的推移,AOF 文件会越来越大。为了防止AOF 文件由于太大而占用大量的磁盘空间,降低性能,Redis 引入了Rewrite 机制对AOF 文件进行压缩

    • 什么是rewrite

      所谓Rewrite 其实就是对AOF 文件进行重新整理。当Rewrite 开启时,主进程redis-server 创建出一个子进程bgrewriteaof,由该子进程完成rewrite 过程。其首先对现有aof 文件进行rewrite 计算,将计算结果写入到一个临时文件,写入完毕后,rename 该临时文件为原aof 文件名,覆盖原有文件。

    • rewrite 计算

      • 读操作命令不写入文件
      • 无效命令不写入文件
      • 过期数据不写入文件
      • 多条命令合并写入文件
    • 开启rewrite

      • 手动开启

        bgrewriteaof
      • 条件自动开启

        文档以及配置
  • AOF-优化配置之同步策略

    • appendfsync
      1. always:写操作命令写入aof_buf 后会立即调用fsync() 系统函数,将其追加到AOF 文件。该策略效率较低,但相对比较安全,不会丢失太多数据,最多就是刚刚执行过的写操作在尚未同步时出现宕机或重启,将这一操作丢失
      2. no: 写操作命令写入aof_buf 后什么也不做,不会调用fsync() 函数。而将aof_buf 中的数据同步磁盘的操作由操作系统负责。Linux 系统默认同步周期为30s。效率较高,
      3. everysec: 默认策略。写操作命令写入aof_buf 后并不会直接调用fsync()。而是每秒调用一次fsync() 系统函数来完成同步。该策略兼顾到了性能与安全,是一种折中方案。
  • AOF-持久化过程

    AOF-持久化过程
    1. Redis 接收到的写操作命令并不是直接追加到磁盘的AOF 文件的,而是将每一条写命令按照redis 通讯协议格式暂时添加到AOF 缓冲区aof_buf
    2. 根据设置的数据同步策略,当同步条件满足时,再将缓冲区中的数据一次性写入磁盘的AOF 文件,以减少磁盘IO 次数,提高性能
    3. 当磁盘的AOF 文件大小达到了rewrite 条件时,redis-server 主进程会fork 出一个子进程bgrewriteaof,由该子进程完成rewrite 过程
    4. 子进程bgrewriteaof 首先对该磁盘AOF 文件进行rewrite 计算,将计算结果写入到一个临时文件,全部写入完毕后,rename 该临时文件为磁盘文件的原名称,覆盖源文件
    5. 如果在rewrite 过程中又有写操作命令追加,那么这写数据会暂时写入aof_rewrite_buf 缓冲区。等将全部rewrite 计算结果写入临时文件后,会将aof_rewrite_buf 缓冲区中的数据写入临时文件,然后再rename 为磁盘文件的原名称,覆盖源文件。
  • RDB AOF 的对比

    • RDB 的优劣势
      • 优势
        1. RDB 文件较小
        2. 数据恢复较快
      • 劣势
        1. 数据安全性较差
        2. 写时复制会降低性能
        3. RDB 文件可读性差
    • AOF 的优劣势
      • 优势
        1. 数据安全性高
        2. AOF 文件可读性强
      • 劣势
        1. 文件较大
        2. 写操作会影响性能
        3. 数据恢复较慢
  • 持久化技术的选型

    1. 官方推荐使用RDB AOF 混合式持久化
    2. 若多数据安全性要求不高,则推荐使用纯RDB 持久化技术
    3. 不推荐使用纯AOF 持久化方式
    4. Redis 仅用于缓存,则无需使用任何持久化技术

事务

  • 事务: 把一组数据库命令放在一起执行,保证操作原子性,要么同时成功,要么同时失败

  • Redis 事务: 允许把一组redis 命令放在一起,把命令进行序列化,然后一起执行,保证部分原子性

  • 开启事务

    1
    2
    3
    4
    # 用来标记一个事务的开始
    multi
    ...

  • exec

    1
    2
    # 用来执行事务队列中所有的命令
    exec
  • redis 的事务只能保证部分原子性

    • 如果一组命令中,有在压入事务队列过程中发生错误的命令,则本事务中所有的命令都不执行,就能够保证事务的原子性

      1
      2
      3
      4
      5
      6
      multi
      set k1 v1
      # 错误语句
      seta k2 v2
      set k3 v3
      exec
      事务的原子性
      事务的原子性
    • 如果一组命令中,在压入队列过程中正常,但是在执行事务队列命令时发生了错误,则只会影响发生错误的命令,不会影响其他命令的执行,不能够保证事务的原子性

      1
      2
      3
      4
      5
      multi
      set k4 v4
      # k4 不是数值型,会报错 但是语法正确
      incr k4
      exec
      未能保证原子性
      未能保证原子性
    • discard

      1
      2
      3
      4
      5
      # 清除所有已经压入队列中的命令,并且结束整个事务
      multi
      set k5 v5
      set k6 v6
      discard
    • watch

      1
      2
      3
      4
      5
      6
      # 监控某一个键,当事务在执行过程中,此键 的值发生变化,则本事务放弃执行 否则 正常执行
      watch key
      multi
      ...
      exec

    • unwatch

      1
      2
      3
      4
      5
      6
      # 放弃监控所有键
      watch key
      unwatch
      multi
      ...
      exec

Redis 消息发布与订阅

  • 简介

    redis 客户端订阅频道,消息的发布者往往在频道上发布消息,所有订阅此频道的客户端都能够接收到消息

  • subscribe

    1
    2
    # 订阅一个或者多个频道的消息
    subscribe ch1 ch2 ch3
  • publish

    1
    2
    # 将消息发布到执行频道
    publish ch1 hello
  • psubscribe

    1
    # 订阅一个或者多个频道的消息,频道名支持通配符

Redis-主从复制

  • 简介

    redis 主从复制: 主多从少、主写从读、读写分离、主写同步复制到从

  • 搭建一主二从redis 集群

    • 搭建三台redis 服务:使用一个redis 模拟三台redis 服务

    • 提供三分redis 配置文件

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      redis6379.conf
      redis6380.conf
      redis6381.conf

      # 修改如下内容
      bind 127.0.0.1
      port 6379 | 6380 | 6381
      pidfile .var/run/redis_6379.pid | pidfile .var/run/redis_6380.pid | pidfile .var/run/redis_6381.id
      logfile "6379.rdb | 6380.rdb | 6381.rdb"
      dbfilename dump6379.rdb | dump6380.rdb | dump6381.rdb

      # 分别使用三个 redis 配置文件,启动三个 redis 服务
      redis-server redis6379.conf &
      redis-server redis6380.conf &
      redis-server redis6381.conf &

      # 通过 redis 客户端分别连接三台 redis 服务
      redis-cli -h 127.0.0.1 -p 6379
      redis-cli -h 127.0.0.1 -p 6380
      redis-cli -h 127.0.0.1 -p 6381

  • 启动三台redis 服务

    启动三台redis服务器
  • 查看三台redis 服务器在集群中的主从角色

    1
    2
    info replication
    # 默认情况下 所有的 redis 服务都是主机,即都能写和读,但是都还没有从机
    replication
    replication
  • 设置主从关系: 设从不设主

    1
    2
    # 在 6380 上执行 slaveof 127.0.0.1 6379
    # 在 6381 上执行 slaveof 127.0.0.1 6379
    6380 6381
    6380 6381
  • 全量复制

    1
    # 一旦主从关系确定,会自动把主库上已有的数据同步复制到从库
    全量复制
    全量复制
  • 增量复制

    1
    # 主库写数据会自动同步到从库
  • 主写从读,读写分离

    1
    # 在从机 set key value 报错
  • 主机宕(dang)

    1
    2
    3
    # 关闭主机 6379 服务
    redis-cli -h 127.0.0.1 -p 6379 shutdown

    主机宕机
    主机宕机
    • 查看从机角色信息

      主机宕机,从机原地待命
      主机宕机,从机原地待命
    • 主机恢复

      重启主机 恢复后的主机信息
      重启主机 恢复后的主机信息
  • 从机宕机

    从机宕机,主机少一个从机,其他从机不变

    从机恢复,需要重新设置主从关系

  • 从机上位(寻找新的主机)

    1. 在从机上断开原来的主从关系

      1
      2
      # Eg: 6380
      slaveof no one
    2. 从新设置主从关系

      1
      slaveof 127.0.0.1 6380

Redis-哨兵模式

  1. 搭建一个一主二从集群架构

  2. 提供哨兵配置文件,在reids 安装目录下创建自定义配置文件

    1
    2
    3
    4
    5
    6
    vim redis_sentinel.conf
    # 添加如下
    sentinel monitor dc-redis 127.0.0.1 6379 1

    # sentinel monitor dc-redis 127.0.0.1 6379 1 表示: 指定监控主机的 ip 地址 port 端口 得到哨兵的投票数(当哨兵投标数大于或者等于次数时切换主从关系)

  3. 启动哨兵服务

    1
    redis-sentinel redis_sentinel.conf
    启动哨兵服务
    启动哨兵服务
  4. 主机宕机

    • 关闭6379 服务

      1
      redis-cli -h 127.0.0.1 -p 6379 shutdown
    • 从机自动变为主机

      从机自动变为主机 哨兵文件变化信息
      从机自动变为主机 哨兵文件变化信息
    • 主机恢复

      主机恢复后自动从属新的主机
      主机恢复后自动从属新的主机

Redis-密码

  • 命令行设置密码

    也可以在配置文件中修改requirepass => vim +798 redis.conf
  • 配置文件中设置密码

    1
    2
    3
    4
    # 密码出现位置为 901 行,编辑起始位置
    vim +901 redis.conf
    # 密码修改为: redis6.4
    requirepass redis6.4
    测试密码:redis6.4

Redis-配置文件详解

  • 快速修改配置

    • redis-cli 连接后

      1
      2
      3
      config get appendonly
      config set appendonly yes
      config rewrite
  • vim 匹配高亮取消

    1. 在命令模式下(ESC)

      关键词匹配搜索,搜索到的关键词高亮
    2. 在命令模式下:/noh,出现找不到匹配模式,高亮将不会显示

  • Includes 模块

    INCLUDES

    关键点说明: 如果需要覆盖配置,那么最好将include 放置在最后一行,使用方式如图中的35-36 行内容格式

  • network 模块

    • bind

    • protected-mode

    • port

    • tcp-backlog*

      说明: tcp-logback 是一个TCP 连接的队列,其主要作用用于解决高并发场景下客户端慢连接问题。这里设置的值就是这个队列的长度。该队列与TCP 连接的三次握手有关。不同的Linux 内核,backlog 队列中存放的元素(客户端连接)类型是不同的

      • Linux 内核2.2 版本之前,该队列中存放的是已完成了第一次握手的所有客户端连接,其中就包含已经完成三次握手的客户端连接。当然,此时的backlog 队列中的连接也具有两种状态: 未完成三次握手的链接状态为SYN_RECEIVED,已完成三次握手的连接状态为ESTABLISHED,只有ESTABLISHED 状态的连接才会被Redis 处理
      • Linux 内核2.2 版本之后TCP 系统中维护了两个队列:SYN_RECEIVED 队列与ESTABLISHED 队列。SYN_RECEIVED 队列中存放的是未完成三次握手的连接,ESTABLISHED 队列中存放的是已完成三次握手的连接。此时的backlog 就是ESTABLISHED 队列
      • 查看当前Linux 的版本内核

        1
        2
        3
        4
        # 方式一
        uname -a
        # 方式二
        cat /proc/version
        version: 3.10.0
      • 查看当前Linux 内核中somaxconn 的值

        1
        cat /proc/sys/net/core/somaxconn
        somaxconn

        TCP 中的backlog 队列的长度在Linux 中由内核参数somaxconn 来决定。所以,Redis 中该队列的长度由Redis 配置文件设置与somaxconn 来共同决定:取它们中的最小值。

        生产环境下(特别是高并发场景下),backlog 的值最好要大一些,否则可能会影响系统性能

        • 修改/etc.sysctl.conf 文件,在文件最后添加如下内容

          1
          vim /etc/sysctl.conf
          1
          2
          # 添加如下内容
          net.core.somaxconn=2048
        • 修改过后可以重启虚拟机,也可以通过如下命令加载,使得配置重新生效

          1
          sysctl -p
    • timeout

    • tcp-keepalive

  • general 模块

    • daemonzie: 该配置可以控制Redis 是否采用守护进程方式,即是否是后台启动.yes 是采用后台启动
    • pidfile: 该配置用于指定Redis 运行时pid 写入的文件,无论是Redis 是否采用守护进程方式,pid 都会写入到该配置的文件
    • loglevel: 日志级别
      1. debug: 可以获取到很多的信息,一般在开发和测试时使用
      2. verbose: 可以获取到很多不太有用的信息,但不像debug 级别那么多
      3. notice: 可以获取到在生产中想获取到的适当多的信息,默认级别
      4. warning: 只记录非常重要/关键的信息
    • logfile: 指定日志文件。如果设置为空串,则强制将日志记录到标准输出设备(显示器)。如果使用的是守护进程启动方式,设置为空串,则意味着会将日志发送到设备/dev/null(空设备)
    • databases: 设置数据库的数量。默认数据库是0 号数据库。可以使用select <dbid> 在每个连接的基础上选择一个不同的数据库,其中dbid 是介于0 databases-1 之间的数字
  • security 模块: 用户设置ACL 权限、Redis 访问密码相关配置。该模块中最常用的就是requirepass 属性

  • clients 模块: 该模块用于设置于客户端相关的属性,其中包含一个属性maxclients.maxclients 用于设置Redis 可并发处理的客户端连接数量,默认值为10000.如果达到了该最大连接数,则会拒绝再来的新连接,并返回一个异常信息: 已达到最大连接数

  • memory management 模块: 该配置可以控制最大可用内存以及线管内容移除问题

    • maxmemory: 将内存使用限制设置为指定的字节数。当达到内存限制时,Redis 将根据选择的住处策略maxmemory-policy 尝试删除符合条件的key
  • Threaded I/O 模块: 该配置模块用于配置Redis 对多线程IO 模型的支持

数据类型操作总结

  • 通用

    通用
  • String

    String
  • Hset

    Hset
  • List

    List
  • Set

    Set
  • SortedSet

    SortedSet