JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)

Redis学习笔记

  • 入门篇
    • Redis介绍
      • 什么是Redis?
      • 什么是NoSQL?
      • NoSQL数据库分类
      • Redis发展历史
      • Redis应用场景
    • Redis单机版安装配置
      • Redis下载
      • Redis安装环境
      • Redis安装
      • Redis启动
        • 前端启动
        • 后端启动(守护进程启动)
        • 后端启动的关闭方式
      • Redis命令行客户端
  • 基础篇
    • Redis数据类型
      • key的设计技巧
      • string类型
        • 常用命令
          • 赋值
          • 取值
          • 取值并赋值
          • 数值增减
            • 递增数字
            • 增加指定的整数
            • 递减数值
            • 减少指定的整数
          • 仅当不存在时赋值
        • 其他命令
          • 向尾部追加值
          • 获取字符串长度
          • 同时设置/获取多个键值
        • 应用场景之自增主键
      • hash类型
        • hash类型介绍
        • 常用命令
          • 赋值
            • 设置一个字段值
            • 设置多个字段值
            • 当字段不存在时赋值
          • 取值
            • 获取一个字段值
            • 获取多个字段值
            • 获取所有字段值
          • 删除字段
          • 增加数字
        • 其他命令
        • string类型和hash类型的区别
        • 应用之存储商品信息
      • list类型
        • ArrayList和LinkedList的区别
        • list类型介绍
        • 常用命令
          • LPUSH、RPUSH
          • LRANGE
          • LPOP、RPOP
          • LLEN
        • 其他命令
          • LREM
          • LINDEX
          • LSET
          • LTRIM
          • LINSERT
          • RPOPLPUSH
        • 应用之商品评论列表
      • set类型
        • set类型介绍
        • 常用命令
          • SADD、SREM
          • SMEMBERS
          • SISMEMBER
        • 集合运算命令
          • SDIFF
          • SINTER
          • SUNION
        • 其他命令
          • SCARD
          • SPOP
      • zset类型
        • zet介绍
        • 常用命令
          • ZADD
          • ZRANGE、ZREVRANGE
          • ZSCORE
          • ZREM
        • 其他命令
          • ZRANGEBYSCORE
          • ZINCRBY
          • ZCARD
          • ZCOUNT
          • ZREMRANGEBYRANK
          • ZREMRANGEBYSCORE
          • ZRANK、ZREVRANK
        • 应用之商品销售排行榜
      • 通用命令
        • KEYS
        • DEL
        • EXISTS
        • EXPIRE(重点)
        • RENAME
        • TYPE
    • Redis消息模式
      • 队列模式
      • 发布订阅模式
    • Redis事务
      • Redis事务介绍
      • 事务命令
        • MULTI
        • EXEC
        • DISCARD
        • WATCH
        • UNWATCH
      • 事务演示
      • 事务失败处理
    • Redis持久化
      • RDB方式
        • 触发快照的时机
        • 设置快照规则
        • RDB快照的实现原理
        • RDB优缺点
      • AOF方式
        • AOF介绍
        • 同步磁盘数据
        • AOF重写原理(优化AOF文件)
        • AOF文件损坏后如何修复
      • 如何选择RDB和AOF

入门篇

Redis介绍

什么是Redis?

  • Redis是C语言开发的一个开源的高性能键值对(Key-Value)内存数据库
  • 它提供五种数据类型来存储值:字符串(string)、散列类型(hash)、列表类型(list)、集合类型(set)、有序集合类型(sortedSet、zSet)
  • 它是一种NoSQL数据库

什么是NoSQL?

  • NoSQL,即Not-Only SQL(不仅仅是SQL),泛指非关系型的数据库
  • 什么是关系型数据库?数据结构是一种有行有列的数据库
  • NoSQL数据库是为了解决高并发、高可用、高可扩展、大数据存储问题而产生的数据库解决方案
  • NoSQL可以作为关系型数据的良好补充,但是不能替代关系型数据库

NoSQL数据库分类

  • 键值(Key-Value)存储数据库
  • 相关产品:Tokyo Cabinet/Tyrant、Redis、Voldemort、Berkeley DB
  • 典型应用:内容缓存,主要用于处理大量数据的高访问负载
  • 数据模型:一系列键值对
  • 优势:快速查询
  • 劣势:存储的数据缺少结构化
  • 列存储数据库
  • 相关产品:Cassandra、HBase、Riak
  • 典型应用:分布式的文件系统
  • 数据模型:以列簇存储,将同一列数据存在一起
  • 优势:查找速度快,可扩展性强,更容易进行分布式扩展
  • 劣势:功能相对局限
  • 文档型数据库
  • 相关产品:CouchDB、MongoDB
  • 典型应用:Web应用(与Key-Value类似,Value是结构化的)
  • 数据模型:一系列键值对
  • 优势:数据结构要求不严格
  • 劣势:
  • 图形数据库
  • 相关产品:Neo4J、InfoGrid、Infinite Graph
  • 典型应用:社交网络
  • 数据模型:图结构
  • 优势:利用图结构相关算法
  • 劣势:需要对整个图做计算才能得出结果,不容易做分布式的集群方案

Redis发展历史

  • 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。

Redis应用场景

  • 内存数据库(登录信息、购物车信息、用户浏览记录等)
  • 缓存服务器(商品数据、广告数据等)(最多使用
  • 解决分布式集群架构中的session分离问题(session共享)
  • 任务队列(秒杀、抢购、12306等等)
  • 分布式锁的实现
  • 支持发布订阅的消息模式
  • 应用排行榜
  • 网站访问统计
  • 数据过期处理(可以精确到毫秒)

Redis单机版安装配置

Redis下载

  • 官网地址:http://redis.io/
  • 中文官网地址:http://www.redis.cn/
  • 下载地址:http://download.redis.io/releases/

Redis安装环境

  • Redis没有官方的windows版本,所以建议在linux系统上安装运行,我们使用CentOS 7作为安装环境
  • 安装镜像:CentOS-7-x86_64-DVD-1810.iso

Redis安装

  • 安装C语言需要的GCC环境
yum install -y gcc-c++
yum install -y wget

JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第1张图片

  • 下载并解压缩Redis源码压缩包
wget http://download.redis.io/releases/redis-3.2.9.tar.gz
tar -zxf redis-3.2.9.tar.gz

JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第2张图片

  • 编译Redis源码,进入redis-3.2.9目录,执行编译命令
cd redis-3.2.9
make

JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第3张图片

  • 安装Redis,需要通过PREFIX指定安装路径
make install PREFIX=/usr/local/server/redis

JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第4张图片

  • 命令说明:
* redis-server:启动redis服务
* redis-cli:进入redis命令客户端
* redis-benchmark:性能监测工具
* redis-check-aof:aof文件进行检查的工具
* redis-check-rdb:rdb文件进行检查的工具
* redis-sentinel:启动哨兵监控服务

Redis启动

前端启动

  • 启动命令:redis-server,直接运行 bin/redis-server将以前端模式启动
  • 关闭命令:Ctrl+C
  • 启动缺点:客户端关闭则redis-server程序结束,不推荐使用此方法
  • 启动图例:
    JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第5张图片

后端启动(守护进程启动)

  • 第一步:拷贝redis-3.2.9/redis.config配置文件到Redis安装目录的bin目录
cp redis.config /usr/local/server/redis/bin
  • 第二步:修改redis.conf
vim redis.conf
# 将`daemonize` 由 no 改为 yes
daemonize yes

# 默认绑定的是回环地址,默认不能被其他机器访问
# bind 127.0.0.1

# 是否开启保护模式,由 yes 改为 no
protected-mode no
  • 第三步:启动服务
./redis-server redis.conf

在这里插入图片描述

后端启动的关闭方式

./redis-cli shutdown

Redis命令行客户端

  • 命令格式:
./redis-cli -h 127.0.0.1 -p 6379

在这里插入图片描述

  • 参数说明
* -h:redis服务器的IP地址
* -p:redis实例的端口号
  • 默认方式:如果不指定主机和端口号,也可以(默认地址是127.0.0.1;默认端口是6379)
./redis-cli

基础篇

Redis数据类型

官方命令大全网址:http://www.redis.cn/commands.html
Redis中存储的数据是通过key-value格式存储数据的,其中value可以定义五种数据类型:

  • String(字符类型)
  • Hash(散列类型)
  • List(列表类型)
  • Set(集合类型)
  • SortedSet(有序集合类型,简称zset)
    注意:在Redis中的命令语句中,命令是忽略大小写的,而key是不忽略大小写的

key的设计技巧

JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第6张图片

string类型

常用命令

赋值
  • 语法:SET key value
  • 示例:
    在这里插入图片描述
取值
  • 语法:GET key
  • 示例:
    在这里插入图片描述
取值并赋值
  • 语法:GETSET key value
  • 示例:
    在这里插入图片描述
数值增减

注意事项

  1. 当value为整数数据时,才能使用以下命令操作数值的增减
  2. 数值增减都是【原子】操作
  3. redis中的每一个单独的命令都是原子性操作。当多个命令一起执行的时候,就不能保证原子性,不过我们可以使用事物和lua脚本来保证这一点
递增数字
  • 语法:INCR key
  • 示例:
    JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第7张图片
增加指定的整数
  • 语法:INCRBY key increment
  • 示例:
    JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第8张图片
递减数值
  • 语法:DECR key
  • 示例:
    JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第9张图片
减少指定的整数
  • 语法:DECRBY key decrement
  • 示例:
    JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第10张图片
仅当不存在时赋值

使用该命令可以实现分布式锁的功能

  • 语法:SETNX key value
  • 示例:
    在这里插入图片描述

其他命令

向尾部追加值
  • 语法:APPEND key value
  • 说明:如果键不存在则将该键的值设置为value,即相当于 SET key value,返回值是追加后字符串的总长度
  • 示例:
    JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第11张图片
获取字符串长度
  • 语法:STRLEN key
  • 说明:返回键值的长度,如果键不存在则返回0
  • 示例:
    JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第12张图片
同时设置/获取多个键值
  • 语法:MSET key value [key value …]MGET key [key …]
  • 示例:
    JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第13张图片

应用场景之自增主键

  • 需求:商品编号、订单号采用INCR命令生成
  • 设计:key命名要有一定的设计
  • 实现:定义商品编号key:items:id
    JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第14张图片

hash类型

hash类型介绍

hash类型也叫散列类型,它提供了字段和字段值的映射。字段值只能是字符串类型,不支持散列类型、集合类型等其他类型。如下:
JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第15张图片

常用命令

赋值

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

设置一个字段值
  • 语法:HSET key field value
  • 示例:
    在这里插入图片描述
设置多个字段值
  • 语法:HMSET key field value [field value …]
  • 示例:
    在这里插入图片描述
当字段不存在时赋值
  • 语法:HSETNX key field value
  • 示例:
    在这里插入图片描述
取值
获取一个字段值
  • 语法:HGET key field
  • 示例:
    在这里插入图片描述
获取多个字段值
  • 语法:HMGET key field [field …]
  • 示例:
    在这里插入图片描述
获取所有字段值
  • 语法:HGETALL key
  • 示例:
    JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第16张图片
删除字段

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

  • 语法:HDEL key field [filed …]
  • 示例:
    JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第17张图片
增加数字
  • 语法:HINCRBY key field increment
  • 示例:
    JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第18张图片

其他命令

  • 判断字段是否存在:HEXISTS key field
    在这里插入图片描述
  • 只获取字段名或字段值:HKEYS keyHVALS key
    JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第19张图片
  • 获取字段数量:HLEN key
    在这里插入图片描述
  • 获取所有字段:HGETALL key
    JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第20张图片

string类型和hash类型的区别

hash类型适合存储那些对象信息,特别是对象属性经常发生【增删改】操作的数据。string类型也可以存储对象数据,将java对象转成json字符串进行存储,这种存储适合【查询】操作

应用之存储商品信息

  • 商品信息字段:商品id、商品名称、商品描述、商品库存、商品好评
  • 定义商品信息的key:商品ID为1001的信息在 Redis 中的key为:【items:1001】
  • 存储商品信息:
    在这里插入图片描述
  • 获取商品信息:
    JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第21张图片

list类型

ArrayList和LinkedList的区别

  • ArrayList使用数组方式存储数据,所以根据索引查询数据速度快,而新增或者删除元素时需要设计到位移操作,所以比较慢。
  • LinkedList使用双向链表方式存储数据,每个元素都记录前后元素的指针,所以插入、删除数据时只是更改前后元素的指针指向即可,速度非常快。然后通过下标查询时需要从头开始索引,所以比较慢,但是如果查询前几个元素或后几个元素速度比较快。
    JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第22张图片
    JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第23张图片

list类型介绍

  • Redis的列表类型可以存储一个有序的字符串列表,常用的操作是向列表两端添加元素,或者获得列表的某一个片段。
  • 列表类型内部是使用双向实现的,所以上列表两端添加元素的时间复杂度为O(1),获取越接近两端的元素速度就越快。这意味着即使是一个有几千万个元素的列表,获取头部或尾部的10条记录也是极快的。

常用命令

JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第24张图片

LPUSH、RPUSH
  • 语法:LPUSH key value [value …]RPUSH key value [value …]
  • 示例:
    在这里插入图片描述
LRANGE
  • 语法:LRANGE key start stop
  • 说明:获取列表中的某一片段,将返回 start—stop之间的所有元素(包括两端的元素),索引从 0 开始,索引可以是负数,如 -1 代表最后边的一个元素
  • 示例:
    在这里插入图片描述
LPOP、RPOP
  • 语法:LPOP keyRPOP key
  • 说明:从列表两端【L-左端,R-右端】弹出元素。从左端弹出一个元素,分两步:一是将列表左边的元素从列表中移除、第二步是返回移除的元素值
  • 示例:
    在这里插入图片描述
LLEN
  • 语法:LLEN key
  • 说明:获取列表中元素的个数
  • 示例:
    在这里插入图片描述

其他命令

LREM
  • 语法:LREM key count value
  • 说明:删除列表中指定个数的值。
- 当 count>0 时,LREM会从列表左边开始删除;
- 当 count<0 时,LREM会从列表右边开始删除;
- 当 count=0 时,LREM删除所有值为value的元素
  • 示例:
    JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第25张图片
    JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第26张图片
    JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第27张图片
LINDEX
  • 语法:LINDEX key index
  • 说明:获取指定索引的元素值
  • 示例:
    在这里插入图片描述
LSET
  • 语法:LSET key index value
  • 说明:设置指定索引的元素值
  • 示例:
    JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第28张图片
LTRIM
  • 语法:LTRM key start stop
  • 说明:只保留列表指定片段,指定返回和LRANGE一致
  • 示例:
    JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第29张图片
LINSERT
  • 语法:LINSERT key BEFORE|AFTER pivot value
  • 说明:向列表中插入元素。该命令首先会在列表中从左到右查找pivot的元素,然后根据第二个参数是BEFROE还是AFTER来决定将value插入到该元素的前面还是后面
  • 示例:
    JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第30张图片
RPOPLPUSH
  • 语法:RPOPLPUSH source destination
  • 说明:将元素从一个列表转移到另一个列表中
  • 示例:
    JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第31张图片

应用之商品评论列表

  • 需求:
* 用户针对某一商品发布评论,一个商品会被不同的用户进行评论,存储商品评论时,要按时间顺序排序
* 用户在前端页面查询该商品的评论,需要按照时间降序排序
  • 分析:使用list存储商品评论信息,KEY是该商品的ID,VALUE是商品评论信息列表
  • 实现:商品编号为1001的商品评论key:【items:comment:1001】
    在这里插入图片描述

set类型

set类型介绍

  • set类型即集合类型,其中的数据是不重复且没有顺序
  • 集合类型和列表类型的对比
集合类型 列表类型
存储内容 至多2^32-1个字符串 至多2^32-1个字符串
有序性
唯一性
  • 集合类型的常用操作是向集合中加入或删除元素、判断某个元素是否存在等,由于集合类型的Redis内部使用值为空的散列表实现,所以这些操作的时间复杂度都是O(1)
  • Redis还提供了多个集合之间的交集、并集、差集的运算

常用命令

SADD、SREM
  • 语法:SADD key member [member …]SREM key member [member …]
  • 说明:添加元素、删除元素
  • 示例:
    JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第32张图片
SMEMBERS
  • 语法:SMEMBERS key
  • 说明:获得集合中的所有元素
  • 示例:
    在这里插入图片描述
SISMEMBER
  • 语法:SISMEMBER key member
  • 说明:判断元素是否在集合中
  • 示例:
    在这里插入图片描述

集合运算命令

SDIFF
  • 语法:SDIFF key [key …]
  • 说明:集合的差集运算 A-B——属于A并且不属于B的元素构成的集合
  • 示例:
    JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第33张图片
SINTER
  • 语法:SINTER key [key …]
  • 说明:集合的交集运算A∩B——属于A并且属于B的元素构成的集合
  • 示例:
    在这里插入图片描述
SUNION
  • 语法:SUNION key [key …]
  • 说明:集合的并集元素A∪B:属于A或者属于B的元素构成的集合
  • 示例:
    JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第34张图片

其他命令

SCARD
  • 语法:SCARD key
  • 说明:获得集合中元素的个数
  • 示例:
    JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第35张图片
SPOP
  • 语法:SPOP key
  • 说明:从集合中弹出一个元素。注意——由于集合是无序的,所以SPOP命令会从集合中随机选择一个元素弹出
  • 示例:
    在这里插入图片描述

zset类型

zet介绍

  • 在set集合类型的基础上,有序集合类型为集合中的每个元素都关联一个分数,这使得我们不仅可以完成插入、删除和判断元素是否存在集合中,还能够获得分数最高或最低的前N个元素、获取指定分数范围内的元素与分数有关的操作。
  • 在某些方面有序集合和列表类型有些相似:
* 二者都是有序的
* 二者都可以获得某一范围的元素
  • 但是,二者有着很大的区别:
* 列表类型是通过链表实现的,获取靠近两端的数据速度极快、而元素增多后,访问中间数据的速度会变慢
* 有序集合类型使用散列表实现,所以即时读取位于中间部分的数据也很快
* 列表中不能简单的调整某个元素的位置,但是有序集合可以(通过更改分数实现)
* 有序集合要比列表类型更耗内存

常用命令

ZADD
  • 语法:ZADD key score member [ score member …]
  • 说明:添加元素。向有序集合中加入一个元素和该元素的分数,如果该元素已经存在则会用新的分数替换原有的分数。返回值是新加入到集合中的元素个数,不包含之前已经存在的元素。
  • 示例:
    在这里插入图片描述
ZRANGE、ZREVRANGE
  • 语法:ZRANGE key start stop [WITHSCORES]ZREVRANGE key start stop [WITHSCORES]
  • 说明:获得排名在某个范围的元素列表
- ZRANGE:按照元素分数从小到大的顺序返回索引从 start 到 stop 之间的所有元素(包含两端的元素)
- ZREVRANGE:按照元素分数从大到小的顺序返回索引从 start 到 stop 之间的所有元素(包含两端的元素)
  • 如果需要获得元素的分数,可以在命令的尾部加上WITHSCORES参数:
  • 示例:
    JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第36张图片
ZSCORE
  • 语法:ZSCORE key member
  • 说明:获取元素的分数
  • 示例:
    在这里插入图片描述
ZREM
  • 语法:ZREM key member [member …]
  • 说明:删除元素。移除有序集合key中的一个或多个成员,不存在的成员将被忽略;当key存在但不是有序集合类型时,返回一个错误
  • 示例:
    在这里插入图片描述

其他命令

ZRANGEBYSCORE
  • 语法:ZRANGEBYSCORE key min max [WITHSCORES]
  • 说明:获得指定分数返回的元素
  • 示例:
    JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第37张图片
ZINCRBY
  • 语法:ZINCRBY key increment member
  • 说明:增加某个元素的分数,返回值是更改后的分数
  • 示例:
    在这里插入图片描述
ZCARD
  • 语法:ZCARD key
  • 说明:获得集合中元素的数量
  • 示例:
    在这里插入图片描述
ZCOUNT
  • 语法:ZCOUNT key min max
  • 说明:获得指定分数范围内的元素个数
  • 示例:
    在这里插入图片描述
ZREMRANGEBYRANK
  • 语法:ZREMRANGEBYRANK key start stop
  • 说明:按照排名范围删除元素
  • 示例:
    JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第38张图片
ZREMRANGEBYSCORE
  • 语法:ZREMRANGEBYSCORE key start stop
  • 说明:按照分数范围删除元素
  • 示例:
    JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第39张图片
ZRANK、ZREVRANK
  • 语法:ZRANK key memberZREVRANK key member
  • 说明:获取元素的排名
- ZRANK:从小到大
- ZREVRANK:从大到小
  • 示例:
    JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第40张图片

应用之商品销售排行榜

  • 需求:根据商品销量对商品进行排序显示
  • 设计:定义商品销量排行榜(sorted set 集合),key为 items:sellsort,分数为商品销售量
    写入商品销售量
  • 商品编号1001的销量是9,商品编号1002的销量是10:
  • 商品编号1001的销量加1:
  • 商品销量前10名:
    JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第41张图片

通用命令

KEYS

  • 语法:KEYS pattern
  • 说明:返回满足给定pattern的所有key
  • 示例:
    JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第42张图片

DEL

  • 语法:DEL key
  • 说明:根据key删除某一条记录
  • 示例:
    JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第43张图片

EXISTS

  • 语法:EXISTS key
  • 说明:确认一个key是否存在
  • 示例:
    在这里插入图片描述

EXPIRE(重点)

  • 语法:
    EXPIRE key seconds:设置key的生存时间(单位:秒)key在多少秒后会自动删除
    TTL key:查看key剩余的生存时间
    PERSIST key:清除生存时间
    PEXPIRE key milliseconds:生存时间设置单位为:毫秒
  • 说明:Redis在实际使用过程中更多的用作缓存,然而缓存的数据一般都是需要设置生存时间的,即:到期后数据销毁
  • 示例:
    JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第44张图片

RENAME

  • 语法:RENAME oldkey newkey
  • 说明:重命名key
  • 示例:
    JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第45张图片

TYPE

  • 语法:TYPE key
  • 说明:显示指定key的数据类型
  • 示例:
    JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第46张图片

Redis消息模式

队列模式

原理:使用list类型的 LPUSHRPOP 实现消息队列:
JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第47张图片
注意事项:

  • 消息接收方如果不知道队列中是否有消息,会一直发送 RPOP 命令,如果这样的话,会每一次都建立一次链接,显然不好
  • 可以使用 BRPOP 命令,它如果从队列中取不出类数据,会一直阻塞,在一定返回内没有取出则返回null

发布订阅模式

  • 订阅消息(subscribe)
    JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第48张图片
subscribe yw-channel
  • 发布消息(publish)
    JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第49张图片
publish yw-channel "hello,everyone!!!"
  • Redis发布订阅命令
    JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第50张图片

Redis事务

Redis事务介绍

  • Redis的事务是通过MULTI、EXEC、DISCARD和WATCH这四个命令来完成的
  • Redis的单个命令都是原子的,所以这里需要确保事务性的对象是命令集合
  • Redis将命令集合序列化并确保处于同一事务的命令集合连续且不被打断执行
  • Redis 不支持回滚操作

事务命令

JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第51张图片

MULTI

  • 语法:MULTI
  • 说明:用于标记事务块的开始,Redis会将后续的命令逐个放入队列,然后使用EXEC命令原子化地执行这个命令序列

EXEC

  • 语法:EXEC
  • 说明:在一个事务中执行所有先前放入队列的命令,然后恢复正常的连接状态

DISCARD

  • 语法:DISCARD
  • 说明:清除所有先前在一个事务中放入队列的命令,然后恢复正常的连接状态

WATCH

  • 语法:WATCH key [key …]
  • 说明:当某个【事务需要按条件执行】时,就要使用这个命令将给定的【键设置为受监控】的状态
  • 注意:使用该命令可以实现 Redis 乐观锁

UNWATCH

  • 语法:UNWATCH
  • 说明:清除所有先前为一个事务监控的键

事务演示

JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第52张图片
JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第53张图片

事务失败处理

  • Redis语法错误(编译期)
    JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第54张图片
  • Redis运行错误
    JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第55张图片

Redis不支持事务回滚(为什么?)

  • 大多数事务失败是因为语法错误或者类型错误,这两种错误在开发阶段都是可以预见的
  • Redis为了性能方面就忽略了事务回滚

Redis持久化

Redis是一个内存数据库,为了保证数据的持久性,他提供了两种持久化方案

  • RDB方式(默认)
  • AOF方式

RDB方式

  • RDB是 Redis 默认采用的持久化方式。
  • RDB是通过快照(snapshotting)完成的,当符合一定条件时,Redis会自动将内存中的数据进行快照并持久化到硬盘。

触发快照的时机

  • 符合自定义配置的快照规则
  • 执行save或者bgsave命令
  • 执行flushall命令
  • 执行主从复制操作

特别说明
Redis启动后会读取RDB快照文件,将数据从硬盘载入到内存
根据数据量大小与结构和服务器性能不同,这个快照条件也需要不同。通常将记录一千万个字符串类型键、大小为1GB的快照文件载入到内存中需要花费20 ~ 30秒钟。

设置快照规则

1. RDB持久化条件

  • 格式:SAVE seconds changes
  • 示例:可以配置多个条件(每行配置一个条件),每个条件之间是 “或” 的关系
save 900 1	:表示15分钟内至少1个键被更改则进行快照
save 300 10	:表示5分钟内至少10个键被更改则进行快照
save 60 1000:表示1分钟内至少1000个键被更改则进行快照

2. 配置dir指定rdb快照文件的位置

# Note that you must specify a directory here, not a file name.
dir ./

3. 配置dbfilename指定rdb快照文件的名称

# The filename where to dump the DB
dbfilename dump.rdb

RDB快照的实现原理

  • 快照过程
* Redis调用系统中的 fork 函数复制一份当前进程的副本(子进程)
* 父进程继续接收并处理客户端发来的命令,而子进程开始将内存中的数据写入硬盘中的临时文件
* 当子进程写入完所有数据后会用该临时文件替换旧的RDB文件,至此,一次快照操作完成

JavaEE 企业级分布式高级架构师(五)Redis学习笔记(1)_第56张图片

  • 注意事项:
* Redis在进行快照的过程中不会修改 RDB 文件,只有快照结束后才会将旧的文件替换成新的,也就是说任何时候 RDB 文件都是完整的。
* 这就使得我们可以通过定时备份 RDB 文件来实现 Redis 数据库备份,RDB 文件是经过压缩的二进制文件,占用的空间会小于内存中的数据,更加利于传输

RDB优缺点

  • 缺点:使用 RDB 方式实现持久化,一旦 Redis 异常退出,就会丢失最后一次快照以后更改的所有数据。这个时候我们就需要根据具体的应用场景,通过组合设置自动快照条件的方式来将可能发生的数据损失控制在能够接受的范围。如果数据相对来说比较重要,希望将损失降到最小,则可以使用 AOF 方式进行持久化
  • 优点:RDB 可以最大化 Redis 性能,父进程在保存 RDB 文件时唯一要做的就是 fork 出一个子进程,然后这个子进程就会处理接下来的所有保存工作,父进程无需执行任何磁盘 I/O 操作。同时这个也是一个缺点,乳沟数据集比较大的时候,fork 可能比较耗时,造成服务器在一段时间内停止处理客户端的请求

AOF方式

AOF介绍

  • 默认情况下 Redis 没有开启 AOF(append only file)方式的持久化
  • 开启 AOF 持久化之后,每执行一条会更改 Redis 中的数据的命令,Redis就会将该命令写入磁盘中的 AOF 文件,这一过程显然会降低 Redis 的性能,但大部分情况下这个影响是能够接受的,另外使用较快的硬盘可以提供 AOF 的性能
  • redis.conf配置修改
# 可以通过修改redis.conf配置文件中的appendonly参数开启
appendonly yes
# AOF文件的保存位置和RDB文件的位置相同,都是通过dir参数设置的
dir ./
# 默认的文件名是appendonly.aof,可以通过appendfilename参数修改
appendfilename appendonly.aof

同步磁盘数据

  • Redis每次更改数据的时候,aof 机制都会将命令记录到 aof 文件,但是实际上由于操作系统的缓存机制,数据并没有实时写入到硬盘,而是进入硬盘缓存,再通过硬盘缓存机制去刷新到文件中保存
  • 参数说明
# 每次执行写入都会进行同步,这个是最安全但是效率比较低的方式
appendfsync always
# 每一秒执行(默认)
appendfsync everysec
# 不主动进行同步操作,由系统区执行,这个是最快但是最不安全的方式
appendfsync no

AOF重写原理(优化AOF文件)

  • Redis 可以再 AOF 文件体积变得过大时,自动地在后台对 AOF 进行重写。重写后的新 AOF 文件包含了恢复当前数据集所需的最小命令集合
  • 整个重写操作时绝对安全的,因为 Redis 在创建新 AOF 文件的过程中,会继续将命令追加到现有的 AOF 文件里面,即使重写过程中发生停机,现有的 AOF 文件也不会丢失。而一旦新 AOF 文件创建完毕,Redis 就会从旧 AOF 文件切换到新 AOF 文件,并对新 AOF 文件进行追加操作。
  • AOF文件有序地保存了对数据库执行的所有写入操作,这些写入操作以Redis协议的格式保存,因此,AOF 文件的内容非常容易被人读懂,对文件进行分析(parse)也很轻松
  • 参数说明:
# 表示当前AOF文件大小超过一次aof文件大小的百分之多少的时候会进行重写。如果之前没有重写过,已启动时aof文件大小为准
auto-aof-rewrite-percentage 100
# 限制允许重写最小aof文件大小,也就是文件大小小于64MB的时候,不需要进行优化
auto-aof-rewrite-size 64mb

AOF文件损坏后如何修复

  • 问题描述:服务器可能在程序正在对 AOF 文件进行写入时停机,如果停机造成了 AOF 文件出错(corrupt),那么 Redis 在重启时会拒绝载入 AOF 文件,从而确保数据的一致性不会被破坏
  • 当发生这种情况时,可以用以下方法类修复出错的 AOF 文件:
- 为现有的 AOF 文件创建一个备份
- 使用 Redis 附带的 redis-check-aof 程序,对原来的 AOF 文件进行修复:
	redis-check-aof --fix readonly.aof
- 重启 Redis 服务器,等服务器载入修复后的 AOF 文件,并进行数据恢复

如何选择RDB和AOF

  • 一般来说,如果对数据的安全性要求非常高的话,应该同时使用两种持久化功能
  • 如果可以承受数分钟以内的数据丢失,那么可以只使用 RDB 持久化
  • 有很多用户都只使用 AOF 持久化,但并不推荐这种方式 :因为定时生成 RDB 快照非常便于进行数据库备份,并且 RDB 恢复数据集的速度也要比 AOF 恢复的速度要快
# 禁止RDB方式
save ""
  • 两种持久化策略可以同时使用,也可以使用其中一种。如果同时使用的话,那么Redis重启时,会优先使用 AOF 文件来还原数据。

你可能感兴趣的:(Redis)