数据库发展剖析:
|==> 单表优化:优化数据库自身的性能
==> 数据拆分:将数据拆分为多个库进行存放
==> 文件缓存:使用IO技术进行缓存,减缓存取的压力
==> 读写分离:一部分库仅负责写入,一部分库仅负责读取,通过分散功能达到分散压力
==> 集群分布:按需求将读写分离整合为一个一个群体,进一步提高性能
==> 逐渐引入NoSql数据库
|--注意每一次迭代都是在之前的基础上进行的
NoSql的分类:
|--K,V键值对数据库:存储方式类似于map集合
|--文档型数据库:采用bson格式进行存储(bson可以理解为二进制的json)
|--列存储数据库:以列为单位进行存储
|--图关系数据库:用来存储关系的数据库
缓存数据分类:
|--实时同步数据:要求缓存中的数据与数据库中的数据时刻保持一致
|--阶段性同步数据:不要求与数据库中所存信息实时一致,只要差异不特别大即可
|--一般为缓存数据添加生存时长来保证差异控制
Redis特性的简单介绍:
|--高性能
|--即无论读速度还是写速度都极快
|--简单稳定
|--源码少且使用稳定
|--可持久化
|--即缓存中的数据可以采用RDB或AOF方式进行持久化
|--高可用集群
|--Redis提供了高可用的主从集群功能,进一步确保系统的安全性
|--丰富的数据类型
|--指Redis是一个key-value模式的存储系统,且value能存储的类型很广
|--功能面广泛
|--Redis提供了数据过期处理、发布订阅、简单事务等功能
|--客户端语言广泛
|--Redis提供了简单的TCP协议,故各种语言都可以很方便的接入Redis完成对客户端的开发
|--支持ACL权限控制
|--即可以针对任意用户与组进行权限上的控制(这是一种细粒度的权限控制)
|--支持多线程IO模型
|--注意Redis最终执行处理器的还是单线程,所谓多线程是指用多线程的方式处理请求并汇总处理队列
Redis的安装与启停:
|--准备linux环境(常用centos系统)
|--在linux中安装gcc,具体安装命令如下
|--yum -y install gcc gcc-c++
|--注意执行此命令需要su指令开启root权限
|--安装gcc是为了可以编译redis文件
|--下载redis安装包并上传至linux系统的磁盘中
|--一般会使用mobaXterm可视化工具简化操作
|--通过tar -zxvf XX -C YY指令解压Redis压缩包
|--XX为需要解压的文件
|--YY为解压后存放的路径
|--进入到解压后的redis文件夹中执行make命令编译redis
|--需要先确保解压文件夹中有Makefile文件
|--进入到解压后的redis文件夹中执行make install命令安装redis
|--启动redis
|--方式一:在linux命令框中执行redis-server命令启动redis
|--注意这种方式启动redis会占用命令行
|--方式二:在linux命令框中执行nohup redis-server &命令启动redis
|--注意这种方式启动redis是在后台启动,不会占用命令行
|--方式三:修改redis核心配置文件后通过配置文件进行启动
|--通过在redis文件夹中执行vim redis.config命令进入修改界面
|--通过/daemonize命令定位守护进程设置行
|--通过i命令开启修改模式
|--将守护进程的默认no模式更改为yes模式(即开启后台启动)
|--通过esc退出修改模式
|--执行:x命令保存修改
|--在linux命令框中执行redis-server XX命令开启redis
|--XX为redis核心配置文件所在的位置,精确到redis.conf文件名
|--注意redis安装好后自动添加至系统全局变量,故在任意目录下均可以启动
|--注意可以通过ps aux | grep redis命令查看redis是否开启
|--关闭redis
|--在linux命令框执行redis-cli shutdown命令关闭redis
深层剖析redis.config配置文件:
|--redis配置文件对大小写不敏感
|-包含专栏
|--redis配置文件中可以使用include XX引入其他的配置文件
|--XX为其他配置文件的路径(需要精确到文件名)
|--注意如果引入的配置文件和当前文件中有内容冲突,以引入位置和冲突位置先后决定使用谁的
|--网络专栏
|--bind 127.0.0.1 -::1 表示让redis仅监听本地ip
|--可以采取注释的方式让其监听所有ip接口
|--protected-mode no 表示仅允许本机用户访问redis
|--可以将no改为yes表示允许所有用户进行访问
|--port 6379 表示当前redis的端口号
|--可以手动修改6379实现自定义端口号
|--通用专栏
|--daemonize no 表示当前不开启守护进程模式(即无法让redis后台运行)
|--可以将no修改为yes开启守护线程模式
|--logfile "" 表示日志输出的文件位置
|--可以在""中编辑自己自定义的日志生成路径(精确到日志文件名)
|--注意如果设置了日志存放路径,需在linux命令框中通过chmod -R 777 XX命令设置操作日志文件夹的权限最大化
|--XX为存放日志的文件夹
|--注意如果不设置日志路径的话,在执行redis的关闭或保存指令时可能会发生错误
|--databases 16 表示redis默认数据库为16个
|--可以手动修改16实现自定义数据库数量
|--always-show-logo yes 表示默认开启redis的logo界面
|--可以将yes改为no关闭logo页面的显示
|--快照专栏
|--save 900 1 表示在900s内至少有1条数据发生了修改则进行持久化
|--实际开发中往往会自定义时间和条数
|--save 300 10 表示在300s内至少有10条数据发生了修改则进行持久化
|--实际开发中往往会自定义时间和条数
|--save 60 10000 表示在60s内至少有10000条数据发生了修改则进行持久化
|--实际开发中往往会自定义时间和条数
|--dbfilename dump.rdb 表示rdb持久化文件的名字为dump.rdb
|--可以通过修改dump.rdb自定义rdb持久化文件名
|--stop-writes-on-bgsave-error yes 表示持久化过程中发生异常仍继续工作
|--可以将yes改为no设置持久化异常时中断工作
|--rdbcompression yes 表示自动压缩rdb持久化文件
|--注意压缩会占用一定资源,如果有需要可以将yes改为no关闭自动压缩
|--rdbchecksum yes 表示在保存rdb持久化文件的时候进行正确性检查
|--可以将yes改为no关闭该检查
|--dir ./ 表示rdb持久化文件的保存路径
|--可以修改./路径自定义rdb持久化文件的保存路径
|--安全专栏
|--#requirepass foobared 表示当前redis无密码
|--我们可以打开注释并修改foobared自定义使用redis的密码
|--注意设置完密码之后,若是使用redis需要auth XX进行授权,XX为密码
|--内存管理专栏
|--maxmemory-policy noeviction 表示当前采用的内存溢出策略为noeviction
|--可以将noeviction设置为其他模式以采用对应的策略,常用策略如下
|--volatile-lru:对设置过期时间的key使用LRU算法删除
|--allkeys-lru:对所有key使用LRU算法删除
|--volatile-lfu:对设置了过期时间的key使用LFU算法删除
|--allkeys-lfu:对所有key使用LFU算法删除
|--volatile-ttl:删除马上要过期的key
|--noeviction:内存溢出了不做移除,直接报错
|--AOF专栏
|--appendonly no 表示默认不开启aof持久化模式,即默认使用rdb持久化
|--可以将no改成yes开启aof持久化模式
|--appendfilename "appendonly.aof" 表示aof持久化文件的名字为appendonly.aof
|--可以通过修改appendonly.aof自定义aof持久化文件名
|--appendfsync everysec 表示每秒执行一次持久化操作
|--可以修改everysec采用其他的策略模式,具体的策略模式如下
|--always:每次修改完都进行持久化
|--neverysec:每间隔一秒自动进行持久化
|--no:不执行aof持久化,让操作系统自己同步数据
使用redis的注意事项:
|--通过执行redis-cli -h XX -P YY -a ZZ命令连接redis,即开启redis客户端
|--XX为redis的ip地址,如果为本机的话可以不写
|--YY为redis的端口号,默认为6379
|--ZZ为连接密码,如果没有设置的话可以不写
|--通过执行exit或者quit命令退出redis客户端
|--注意确保进入redis客户端启动的环境下执行该指令才有效
|--通过执行redis-benchmark -h XX -p YY -a ZZ -c KK -n LL命令测试所连接redis的性能
|--XX为redis的ip地址,如果为本机的话可以不写
|--YY为redis的端口号,默认为6379
|--ZZ为连接密码,如果没有设置的话可以不写
|--KK为需要模拟的客户端数量
|--ZZ为需要模拟的每个客户端所发送的数据量
|--通过执行config get XX命令可以查看redis配置文件中的属性值
|--XX为配置文件中的属性名
|--注意确保进入redis客户端启动的环境下执行该指令才有效
|--通过执行info replication命令可以查看当前库的相关信息
|--通过执行select XX命令切换当前所在的数据库
|--XX为需要切换的数据库
|--redis默认有16个数据库(即0~15),默认使用的是第0个数据库
|--注意确保进入redis客户端启动的环境下执行该指令才有效
|--通过执行dbsize命令查看当前数据库所存数据的数量
|--注意确保进入redis客户端启动的环境下执行该指令才有效
|--通过执行flushdb命令清空当前数据库
|--注意确保进入redis客户端启动的环境下执行该指令才有效
|--通过执行flushall命令清空所有数据库
|--注意确保进入redis客户端启动的环境下执行该指令才有效
|--通过执行keys *命令查看当前数据库中所有的key值
|--注意确保进入redis客户端启动的环境下执行该指令才有效
|--通过执行exists XX命令查看当前数据库中是否存在指定的key值
|--XX为需要检索的key值
|--注意存在的话返回1,不存在的话返回0
|--注意确保进入redis客户端启动的环境下执行该指令才有效
|--通过执行move XX YY命令移除当前数据库中指定的key值
|--XX为需要移除的key值
|--YY为需要移动到的数据库(若设置为本数据库表示删除该条数据)
|--注意确保进入redis客户端启动的环境下执行该指令才有效
|--通过执行expire XX YY命令设置指定数据过期时间
|--XX为需要设置过期时间数据的key值
|--YY用于设置过期的时间,单位为秒
|--注意确保进入redis客户端启动的环境下执行该指令才有效
redis对八种数据类型的支持(注意进入redis客户端启动的环境下执行以下指令才有效):
|--String类型
|--通过执行type XX命令查看指定数据的类型
|--XX为需要查看类型的数据key值
|--通过执行setnx XX YY命令在插入数据前进行存在性判断
|--XX用于设置需要存入数据的key值
|--YY用于设置需要存入数据的value值
|--注意使用该命令存数据,若key值已经存在则会插入失败
|--通过执行mset XX YY..命令插入多组数据
|--XX用于设置需要存入数据的key值
|--YY用于设置需要存入数据的value值
|--通过执行mget XX..命令查询多组数据
|--XX为需要查找的数据的key值
|--通过执行set XX:YY:ZZ KK命令将数据模拟成对象形式插入
|--XX用于设置所插入对象的key值
|--YY用于设置所插入对象的名字
|--ZZ用于设置所插入对象的属性名
|--KK用于设置所插入对象的属性值
|--通过执行get XX:YY:ZZ命令查询模拟成对象形式插入数据的属性值
|--XX为所插入对象的key值
|--YY为所插入对象的名字
|--ZZ为所插入对象的属性名
|--通过执行getset XX YY命令同时执行查询和存入操作
|--XX为需要查询数据的key值
|--YY用于设置需要插入的数据
|--注意该方法会先取出旧值进行显示(没有的话则返回nil),之后才将新值注入
|--通过执行append XX YY命令给指定数据追加字符串
|--XX为需要被追加的数据的key值
|--YY为需要追加的数据
|--注意如果被追加的key不存在,会自动自行set命令创建key
|--通过执行strlen XX命令查看指定数据的长度
|--XX为需要查看的数据的key值
|--通过执行incr XX命令使数据自增一
|--XX为需要自增的数据的key值
|--注意使用该命令前提是所存的字符类型能转化为数值型
|--通过执行decr XX命令使数据自减一
|--XX为需要自减的数据的key值
|--注意使用该命令前提是所存的字符类型能转化为数值型
|--通过执行incrby XX YY命令使数据自增指定步长
|--XX为需要自增的数据的key值
|--YY为需要自增的步长
|--注意使用该命令前提是所存的字符类型能转化为数值型
|--通过执行decrby XX YY命令使数据自减指定步长
|--XX为需要自减的数据的key值
|--YY为需要自减的步长
|--注意使用该命令前提是所存的字符类型能转化为数值型
|--通过执行getrange XX YY ZZ命令截取字符串片段
|--XX为需要被截取的数据的key值
|--YY为截取的起始位置(包括该位置)
|--ZZ为截取的结束位置(包括该位置)
|--通过执行setrange XX YY ZZ命令替换字符串中的片段
|--XX为需要进行替换操作数据的key值
|--YY为需要进行替换的位置
|--ZZ用于设置替换的数据
|--List类型(可以将redis中的list理解成java中的队列)
|--通过执行lpush XX YY命令从左边向集合中插入值
|--XX为集合的名字
|--YY为需要插入的数据
|--通过执行rpush XX YY命令从右边向集合中插入值
|--XX为集合的名字
|--YY为需要插入的数据
|--通过执行lrange XX YY ZZ命令从左到右查询集合中存放的数据片段
|--XX为集合的名字
|--YY用于设置查询的起始位置(包括该位置)
|--ZZ用于设置查询的结束位置(包括该位置)
|--通过执行lpop XX命令移除左边第一个数据
|--XX为集合的名字
|--通过执行rpop XX命令移除右边第一个数据
|--XX为集合的名字
|--通过执行lindex XX YY命令获取集合中指定下标的数据
|--XX为集合的名字
|--YY为需要获取数据的下标
|--注意该指令是按照下标从左到右递增的情况进行检索
|--通过执行llen XX指令获取集合的长度
|--XX为集合的名字
|--通过执行lrem XX YY ZZ命令移除集合中的指定元素
|--XX为集合的名字
|--YY为需要移除的元素个数(适用于有多个同名元素的情况)
|--ZZ为需要移除的数据名
|--注意该指令是从左到右进行检索
|--通过执行ltrim XX YY ZZ命令从左到右截取集合中存放的数据片段
|--XX为集合的名字
|--YY用于设置截取的起始位置(包括该位置)
|--ZZ用于设置截取的结束位置(包括该位置)
|--通过执行rpoplpush XX YY命令将一个集合的最右一个元素移动到另一个集合的最左位置
|--XX为需要移出元素的集合名字
|--YY为需要移入元素的集合名字
|--通过执行lset XX YY ZZ命令向集合中的指定位置添加元素
|--XX为集合的名字
|--YY为需要添加元素的位置
|--ZZ为需要添加的元素
|--注意该指令是按下标从左到右递增的情况进行检索
|--注意执行该指令要确保该集合是存在的,否则会报错
|--通过执行linsert XX YY ZZ KK命令向集合中指定元素的前面或后面添加元素
|--XX为集合的名字
|--YY为before或者after,表示前或后
|--ZZ表示在哪个元素前或后进行添加
|--KK为需要添加的元素
|--Set类型
|--通过执行sadd XX YY命令向集合中插入数据
|--XX为集合的名字
|--YY为需要插入的数据
|--注意set类型中不能添加重复元素,否则会报错
|--通过执行sismember XX YY命令判断集合中是否包含指定元素
|--XX为集合的名字
|--YY为需要进行判别的数据
|--注意如果存在的话返回1,不存在的话返回0
|--通过执行scard XX命令查看当前集合的长度
|--XX为集合的名字
|--通过执行smembers XX命令查看当前集合的所有元素
|--XX为集合的名字
|--通过执行srem XX YY命令移除集合中的指定元素
|--XX为集合的名字
|--YY为需要移除的元素
|--通过执行srandmember XX YY命令随机从集合中抽取指定个数的元素
|--XX为集合的名字
|--YY用于设置需要随机抽取的个数(不设置的话默认为1)
|--通过执行spop XX命令从集合中随机移除一个元素
|--XX为集合的名字
|--通过执行smove XX YY ZZ命令将一个集合中的指定元素移动到另一个集合中
|--XX为需要移出元素集合的名字
|--YY为需要移入元素集合的名字
|--ZZ为需要进行移动的元素
|--通过执行sdiff XX YY命令取两个集合的差集
|--XX为主集合的名字
|--YY为参照集合的名字
|--注意返回的结果是前一个集合去除后一个集合中元素后的结果
|--通过执行sinter XX YY命令取两个集合的交集
|--XX为第一个集合的名字
|--YY为第二个集合的名字
|--通过执行sunion XX YY命令取两个集合的并集
|--XX为第一个集合的名字
|--YY为第二个集合的名字
|--Hash类型(可以理解为在redis的key-value层级下又分了一层key-value)
|--通过执行hset XX YY ZZ命令向集合中存储数据
|--XX为集合的名字
|--YY用于设置集合中所存元素的key值
|--ZZ用于设置集合中所存元素的value值
|--通过执行hget XX YY命令获取集合中元素的值
|--XX为集合的名字
|--YY为集合中所存元素的key值
|--通过执行hgetall XX获取集合中所有的键值对
|--XX为集合的名字
|--注意结果会将key和value均展示
|--通过执行hkeys XX命令获取集合中的所有key值
|--XX为集合的名字
|--通过执行hvals XX命令获取集合中的所有value值
|--XX为集合的名字
|--通过执行hdel XX YY命令删除集合中的指定键值对
|--XX为集合的名字
|--YY为需要删除的键值对的key值
|--通过执行hlen XX命令查询集合的长度
|--XX为集合的名字
|--通过执行hexists XX YY命令查看集合中是否存在指定键值对
|--XX为集合的名字
|--YY需要进行检索的键值对的key值
|--通过执行hincrby XX YY ZZ命令使数据自增指定步长
|--XX为集合的名字
|--YY为需要自增的键值对的key值
|--ZZ为需要自增的步长
|--注意使用该命令前提是所存的字符类型能转化为数值型
|--通过执行hdecrby XX YY ZZ命令使数据自减指定步长
|--XX为集合的名字
|--YY为需要自减的键值对的key值
|--ZZ为需要自减的步长
|--注意使用该命令前提是所存的字符类型能转化为数值型
|--ZSet类型
|--通过执行zadd XX YY ZZ命令向集合中添加数据
|--XX为集合的名字
|--YY用于设置所添加元素所绑定的权重
|--ZZ为需要添加的数据
|--通过执行zrange XX YY ZZ命令查询集合中存放的数据片段
|--XX为集合的名字
|--YY用于设置查询的起始位置(包括该位置)
|--ZZ用于设置查询的结束位置(包括该位置)
|--通过执行zrangebyscore XX YY ZZ KK命令对集合中的元素进行片段升序排列
|--XX为集合的名字
|--YY为升序排列的起点(负无穷为-inf)
|--ZZ为升序排列的终点(正无穷为+inf)
|--KK用于设置是否需要将元素的权重也进行打印,要的话则设置为withscores
|--注意使用该命令时终点值必须小于起点值
|--通过执行zrevrangebyscore XX YY ZZ KK命令对集合中的元素进行片段降序排列
|--XX为集合的名字
|--YY为降序排列的起点(正无穷为+inf)
|--ZZ为降序排列的终点(负无穷为-inf)
|--KK用于设置是否需要将元素的权重也进行打印,要的话则设置为withscores
|--注意使用该命令时起点值必须大于终点值
|--通过执行zrem XX YY命令移除集合中的指定元素
|--XX为集合的名字
|--YY为需要移除的元素
|--通过执行zcard XX命令获取集合中的元素个数
|--XX为集合的名字
|--通过执行zcount XX YY ZZ命令获取集合中指定权重之间元素的个数
|--XX为集合的名字
|--YY为起始权重
|--ZZ为结束权重
|--Geospatial类型
|--通过执行geoadd XX YY ZZ KK命令添加地理位置
|--XX用于设置所存储地理位置在数据库中所绑定的集合名字
|--YY用于设置所存地理位置的经度
|--ZZ用于设置所存地理位置的纬度
|--KK用于设置所存地位位置的名字
|--通过执行geopos XX YY命令获取所存地理位置的经纬度
|--XX为所存储地理位置在数据库中所绑定的集合名字
|--YY为所存地理位置的名字
|--通过执行geodist XX YY ZZ KK命令获取两个地理位置之间的距离
|--XX为所存储地理位置在数据库中所绑定的集合名字
|--YY、ZZ为所存地理位置的名字
|--KK用于设置所得到距离的单位
|--注意只要两个地理位置之间有一个不存在则返回nil
|--通过执行georadius XX YY ZZ KK JJ命令获取指定地理位置指定范围内的地理位置
|--XX为所存储地理位置在数据库中所绑定的集合名字
|--YY为地理位置的经度
|--ZZ为地理位置的维度
|--KK用于设置具体的范围大小
|--JJ用于设置范围大小的单位
|--通过执行georadiusbymember XX YY ZZ KK命令获取指定地理位置指定范围内的地理位置
|--XX为所存储地理位置在数据库中所绑定的集合名字
|--YY为地理位置的名称
|--ZZ用于设置具体的范围大小
|--KK用于设置范围大小的单位
|--Hyperloglog类型
|--通过执行pfadd XX YY...命令向集合中添加数据
|--XX为集合的名字
|--YY为需要存储的数据
|--通过执行pfcount XX命令统计集合中不重复数据的个数
|--XX为集合的名字
|--通过执行pfmerge XX YY ZZ命令将两个集合不重复的部分合并成一个新的集合
|--XX为新集合的名字
|--YY,ZZ为需要合并的集合的名字
|--Bitmap类型
|--通过执行setbit XX YY ZZ命令向集合中插入键值对
|--XX为集合的名字
|--YY用于设置键值对的key值
|--ZZ用于设置键值对的value值,注意bitmap类型中的value值只能为0或1
|--通过执行getbit XX YY命令获取集合中所存的键值对
|--XX为集合的名字
|--YY为键值对的key值
|--通过执行bitcount XX命令获取集合中value为1的键值对个数
|--XX为集合的名字
redis对事务的支持:
|--执行multi命令开启事务
|--命令入队
|--该环节正常编写命令即可,redis会自动将我们编写的指令放入队列中
|--执行exec命令执行事务
|--redis会按入队的顺序依次将队列中的命令执行完
|--执行discard命令丢弃事务
|--注意此时队列中已有的命令会丢失
|--redis事务中的异常
|--编译型异常(即代码错误):此时事务中所有的命令均不会被执行
|--运行时异常(即语法类错误):此时事务中除了报错的指令不执行,其余指令依旧执行
|--可以理解为redis中的事务不具有原子性
|--redis中的乐观锁(即监控机制)
|--通过执行watch XX命令给数据上锁
|--监视机制会对上锁的数据进行监视,看在当前事务提交前是否有人修改了上锁数据,如果有则当前事务一定提交失败
|--注意锁机制一定需要配合事务一起使用才有意义
|--注意如果watch的对象已经被修改,需要先通过unwatch进行解锁才可以重新监视
通过jedis操作redis(即使用java操作redis):
|--导入jedis依赖
|--通过new Jedis(XX,YY)连接redis并得到jedis的对象
|--XX为需要连接redis的ip地址
|--YY为需要连接redis的端口号
|--注意jedis有很多种重载的构造函数,根据需要的连接参数选择对应的即可
|--通过jedis对象调用各种方法完成对redis库的基础操作
|--注意jedis操作redis所调用的方法和在linux命令框中操作redis的方法名字一模一样
|--通过jedis对象调用close方法可以关闭与当前redis的连接
springboot整合redis:
|--依赖准备
|--创建项目时在nosql分类下勾选上springData redis即可
|--springboot会自动为我们添加与之相关的各种启动依赖
|--配置连接
|--在springboot核心配置文件中通过spring.redis.host=XX设置所连接redis的ip地址
|--XX为redis的ip地址
|--在springboot核心配置文件中通过spring.redis.port=XX设置所连接redis的端口号
|--XX为redis的端口号
|--注意在核心配置文件中对redis的配置还有很多,开发中我们根据具体需求进行设置即可
|--springboot提供的模板对象
|--RedisTemplate
|--redisTemplate对象调用opsForValue方法可以获得用于操作String类型的对象
|--redisTemplate对象调用opsForList方法可以获得用于操作List类型的对象
|--redisTemplate对象调用opsForSet方法可以获得用于操作Set类型的对象
|--redisTemplate对象调用opsForHash方法可以获得用于操作Hash类型的对象
|--redisTemplate对象调用opsForZSet方法可以获得用于操作ZSet类型的对象
|--redisTemplate对象调用opsForGeo方法可以获得用于操作Geospatial类型的对象
|--redisTemplate对象调用opsForHyperloglog方法可以获得用于操作Hyperloglog类型的对象
|--注意类型对象操作redis所调用的方法和在linux命令框中操作redis的方法名字基本一致
|--注意一些常用的方法直接用redisTemplate对象调用即可(例如数据库连接和简单的crud)
|--注意RedisTemplate模板对象采用的是jdk序列化方式
|--StringRedisTemplate
|--除了序列化方式采用的是string序列化方式之外,其余操作同RedisTemplate模板对象
|--注意两种模板对象都是springboot为我们提供好的,要用的话进行注入即可
|--连接redis
|--使用模板对象调用setConnectionFactory(XX)方法即可与redis建立连接
|--XX为RedisConnectionFactory的实例化对象
|--注意连接redis的操作框架已经为我们做了,如果使用框架提供的模板对象默认会自动建立连接
|--注意早期springboot集成redis时底层用的是jedis,现在被lettuce所替代
|--jedis连接redis用的是直连,容易产生线程不安全的隐患
|--lettuce连接redis采用的一个实例可以被多个线程共享的方式进行连接,相对来说更安全
|--注意实际开发中为了更好的操作redis,我们通常会自定义redis模板对象并重写序列化规则
|--注意使用redis存的对象一定要进行序列化,否则会导致存储异常
redis持久化机制:
|--rdb持久化
|--流程概述
|--如果接收到需要进行持久化的请求,父进程会开辟出一个新的子进程单独进行持久化操作
|--用于持久化的子进程会将数据先写入一个临时rdb文件中
|--等到所有数据持久化完毕后直接将这个临时rdb文件替换之前存储的rdb文件
|--触发机制
|--在执行过程中满足我们制定的save规则时会生成rdb文件
|--在执行flushall命令时会生成rdb文件
|--在退出redis时会生成rdb文件
|--恢复机制
|--只要确保生成的rdb文件位于redis的启动目录下,在redis启动时会自动检索并恢复数据
|--注意由于rdb持久化的特殊触发机制,如果redis突然宕机,最后一次修改的数据可能无法被持久化
|--aof持久化
|--流程概述
|--父进程会开辟一个新的子进程将每个操作指令记录到一个临时aof文件中
|--等到所有指令执行完毕后直接将这个临时aof文件替换之前存储的aof文件
|--开启aof模式
|--注意aof持久化默认是关闭的,要用的话需要在配置文件中手动开启
|--注意aof持久化和rdb持久化并不冲突,可以同时存在(若同时存在会优先执行aof文件进行数据恢复)
|--触发机制
|--在redis运行过程中只要满足了我们在配置文件中制定的aof持久化规则即触发
|--恢复机制
|--只要确保生成的aof文件位于redis的启动目录下,在redis启动时会自动检索并重新执行一遍文件中所存的指令
|--修复aof持久化文件异常
|--执行redis-check-aof --fix XX命令修复aof持久化文件
|--XX为aof持久化文件的名字,一般为appendonly.aof
|--注意需要在redis-check-aof修复工具所在的目录内执行该命令才有效
|--注意如果aof持久化文件异常,会导致数据无法恢复,进而导致redis连接失败
redis订阅发布:
|--通过执行subscribe XX命令订阅一个频道
|--XX为频道的名字
|--通过执行publish XX YY命令在指定频道发布消息
|--XX为频道的名字
|--YY为需要发送的消息
|--通过执行unsubscribe XX命令退订一个评到
|--XX为频道的名字
|--注意只要所订阅的频道一有消息发布,订阅端会自动接收并展示
redis主从复制:
|--简单了解
|--将一台redis服务器的数据复制到其他的redis服务器上,被复制方称为主节点(master),复制方称为从节点(slave)
|--注意复制只能是单向的,即只能由主节点到从节点
|--注意主从的概念是相对的,一台redis服务器既可以做主节点,也可以做从节点
|--注意每一台redis最多只能有一个主节点,但可以有多个从节点
|--注意实际开发中最少也会采用一主二从的方式减少宕机带来的风险
|--连接主节点
|--方式一:在从机上执行slaveof XX YY命令连接指定的主节点
|--XX为需要连接主节点的ip地址
|--YY为需要连接主节点的端口号
|--注意这种方式的主从配置是暂时性的(即断开连接后再重启失去之前的主从配置映射)
|--方式二:在从机的配置文件中连接指定的主节点
|--在配置文件的复制专栏打开replicaof <masterip> <masterport>行注释
|--将<masterip> <masterport>换成需要连接的主节点ip即端口号
|--注意如果主节点有密码还需要打开masterauth <master-password>行注释并设置对应主节点密码
|--注意这种方式的主从配置是永久性的
|--主从复制细节点
|--注意只有主机才可以写,从机只负责读取
|--注意即使主机断开了,从机依旧会连接着主机,等到主机再次上线进行写入,从机仍能正常读取
|--注意从机断开连接后再次上线,只要确保主从关系维持着,就能自动同步从机断开期间主机所写入的数据
|--注意主从复制分为全量复制和增量复制
|--全量复制指主机将所有数据全部同步给从机
|--增量复制指主机仅将新增的数据同步给从机
|--注意只要从机对主机发起重新连接,默认先执行一次全量复制
|--注意如果一个节点既是主节点又是从节点,redis会对其应用从节点规则(即无法执行写入操作)
|--注意可以通过slaveof no one命令让从机放弃从机身份变成一个新的主节点
|--注意一般在主节点长期失联的情况才会这样做
|--哨兵模式
|--流程概述
|--服务器会为每一个哨兵分配一个单独的子进程,用于监视对应的主节点
|--一旦主节点长期失联会被哨兵监测到并在失联主节点的所有从节点中进行一轮投票,选出新的主节点
|--注意产生新的主节点后若之前失联的主节点重新上线,会自动将其作为新主节点的从节点
|--可以将哨兵模式理解为slaveof no one命令的自动版
|--具体操作
|--自定义一个哨兵配置文件,常用配置如下
|--port XX :设置哨兵端口
|--XX为端口号
|--sentinel monitor XX YY ZZ KK :设置哨兵监视规则
|--XX用于自定义需要监视的主节点名称
|--YY为需要监视的主节点ip
|--ZZ为需要监视的主节点端口号
|--KK用于设置有几个哨兵认为该节点失效后才认定其失效
|--sentinel auth-pass XX YY :设置哨兵连接主节点时需要的密码
|--XX为设置监视规则时自定义的主节点名称
|--YY为连接主节点的密码
|--通过redis-sentinel XX命令启动哨兵监视
|--XX为哨兵配置文件的路径(需要精确到文件名)
|--注意该命令必须在redis-sentinel插件所在的目录下执行才可以生效
redis缓存穿透:
|--问题概述
|--大量用户请求的数据在缓存和数据库中都无法找到,即大量用户的请求都变成直接向数据库发起导致数据库负载过大
|--注意如果一个缓存中存在的数据被极高频率的请求,也有可能导致缓存中的该数据失效进而触发缓存穿透现象
|--业内又将这种情况称为缓存击穿
|--解决策略
|--方式一:布隆过滤器
|--将所有数据以特定的规则进行存储
|--在控制层添加过滤器进行校验,如果满足规则再放行,不满足则丢弃,以此减少数据库压力
|--方式二:缓冲空对象
|--当第一次查询数据库发现无匹配内容时在缓存层创建一个可以匹配的空对象
|--后续查询相同的内容时就可以直接在缓存中读取该空对象,以此减少数据库压力
redis缓存雪崩:
|--问题概述
|--因为各方面的原因,整个缓存层整体崩溃,导致所有请求直面数据库
|--解决策略
|--异地多活:即搭建集群环境,确保一台服务器宕机后还有服务器可以使用
|--限流降级:即在监测到缓存失效后,通过加锁或队列控制限制同一时间能操作数据库的线程数量
|--数据预热:即事先将可能大量被请求的数据放到缓存中,并将过期时间分散设置