Redis
Redis安装包和客户端图形化管理工具下载地址:https://download.csdn.net/download/qq_42795277/12859382
- Redis(Remote DIctionary Server),是用c语言开发的一个开源的高性能键值对(key-value)数据库
特征
-
数据间没有必然的关联关系
-
内部采用单线程机制进行工作
-
高性能,官方提供测试数据,50个并发执行100000请求,读取速度是110000次/s,写的速度是81000次/s
-
多数据类型支持
1:字符串类型 string
2:列表类型 list
3:散列类型 hash
4:集合类型 set -
支持持久化,可以进行数据灾难恢复
-
为热点数据加速查询(主要场景)
NoSQL
- NoSQL(Not-Only SQL),泛指非关系型的数据库,作为关系型数据库的补充
- 作用:应对基于海量用户和海量数据前提下的数据处理问题
特征
- 可扩容,可伸缩
- 大数据量下高性能
- 灵活的数据模型
- 高可用
Redis的操作
操作 | 说明 |
---|---|
redis-server | 服务器启动命令 |
redis-cli | 客户端启动命令 |
redis.conf | redis核心配置文件 |
redis-check-dump | RDB文件检查工具(快照持久化文件) |
redis-check-aof | AOP文件修复工具 |
Redis服务启动
操作 | 说明 |
---|---|
redis-server [ --port port ] | 启动服务器(参数启动),例如 :redis-server --port 6379 |
redis-server config_file_name | 启动服务器-配置文件启动,例如:reids-server redis.conf |
Redis客户端启动
操作 | 说明 |
---|---|
redis-cli [ -h host ] [ -p port ] | 启动客户端,例如:redis-cli -h 192.168.100.128 -p 6379 |
Redis基础配置设定
Redis基础环境设置约定
操作 | 说明 |
---|---|
mkdir conf | 创建配置文件存储目录 |
mkdir data | 创建服务器文件存储目录(包含日志,数据,临时配置文件等) |
服务端设定
操作 | 说明 |
---|---|
daemonize yes|no | 设定服务器已守护进程的方式运行,开启后服务器控制台中将打印服务器运行信息(同日志内容跟相同) |
bind ip | 绑定主机地址 |
port port | 设置服务器端口号 |
dir path | 设置服务器文件保存地址 |
客户端配置
操作 | 说明 |
---|---|
maxclients count | 服务器允许客户端做大连接数量,默认0,表示无限制。当客户端连接到达上限后,Redis会拒绝新的连接 |
timeout seconds | 客户端闲置等待最大时间,达到最大值后关闭对应的连接,如需关闭该功能,设置为0 |
日志配置
操作 | 说明 |
---|---|
loglevel debug|verbose|notice|warning | 设置服务器以指定日志记录级别 |
logfile filename | 日志记录文件名 |
注意:日志级别开发期设置为verbose即可,生产环境中配置为notice,简化日志输出量,降低写日志IO的频度
Redis的基本操作
退出客户端
操作 | 说明 |
---|---|
quit | 退出客户端 |
exit | 退出客户端 |
CTRL+ C | 快捷键方式退出客户端 |
Redis数据存储格式
- redis自身是一个Map,其中所有的数据都是采用 key:value的形式存储
- 数据类型指的是存储的数据的类型,也就是value部分的类型,key部分永远都是字符串
Redis的常用5种数据类型
- string
- hash
- list
- set
- sorted_set/zset (应用性较低)
string数据类型
- 存储的数据:单个数据,最简单的数据存储类型,也是最常用的数据存储类型
- 存储数据的格式:一个存储空间保存一个数据
- 存储内容:通常使用字符串,如果字符串以整数的形式展示,可以作为数字操作使用
string类型数据的基本操作
操作 | 说明 |
---|---|
set key value | 添加/修改数据 |
get key | 获取数据 |
del key | 删除从数据 |
setnx key value | 判定性添加数据 |
mset key1 value1 key2 value2 … | 添加/修改多个数据 |
mget key1 key2 … | 获取多个数据 |
strlen key | 获取数据字符个数 |
append key value | 追加信息到原始信息后部(如果原始信息存储则追加,否则新建) |
incr key | 设置数值数据自增 |
incrby key increment | 设置数值数据自增指定的整数数值 |
incrbyfloat key increment | 设置数值数据自增指定的小数数值 |
decr key | 设置数值数据自减 |
decrby key increment | 设置数值数据自减指定的整数数值 |
setex key seconds value | 设置指定多少秒后数据过期 |
psetex key milliseconds value | 设置指定多少毫秒后数据过期 |
string类型数据操作的注意事项
1: 数据操作不成功的反馈与数据正常操作之间的差异
-
表示运行结果是否成功
1:(integer)0 ➡false 失败
2:(integer)1 ➡true 成功 -
表示运行结果数值
1:(integer) 3 ➡ 3 3个
2:(integer) 1 ➡ 1 1个
2:数据未获取到时,对应的数据为(nil),等同于null
3:数据最大存储量:512MB
4:string在redis内部存储默认就是一个字符串,当遇到增减类操作incr,decr时会转成数值型进行计算
5:按数值进行操作的数据,如果原始数据不能转成数值,后超越redis数值上限范围,将报错;9223372036854775807(是Java中Long型数据最大值Long.MAX_VALUE)
6:redis所有的操作都是原子性的,采用单线程处理所有业务,命令是一个一个执行的,因此无需考虑并发带来的数据影响
hash数据类型
- 对一系列存储的数据进行编组,方便管理,典型应用存储对象信息
- 一个存储空间保存多个键值对数据
- 底层使用哈希表结果实现数据存储
hash存储结构优化
- 如果field数据量较少,存储结构优化为类数组结构
- 如果field数据量较多,存储结构使用HashMap结构
Hash数据类型的基本操作
操作 | 说明 |
---|---|
hset key field value | 添加/修改数据 |
hget key field | 获取数据 |
hgetall key | 获取数据 |
hdel key field1 [field2] | 删除数据 |
hsetnx key field value | 设置field的值,如果该field存在则不做任何操作 |
hmset key field1 value1 field2 value2 … | 添加/修改多个数据 |
hmget key field1 field2 … | 获取多个数据 |
hlen key | 获取哈希表中字段的数量 |
hexists key field | 获取哈希表中是否存在指定字段 |
hkeys key | 获取哈希表中所有字段名 |
hvals key | 获取哈希表中所有字段值 |
hincrby key field increment | 设置字段的数据值自增 |
hincrbyfloat key field increment | 设置字段的数据值自增指定的小数值 |
hash数据类型操作的注意事项
- hash类型中value只能存储字符串,不允许存储其它数据类型,不存在嵌套现象,如果数据为获取到,对应的值为(nil)
- 每个hash可以存储 232-1个键值对
- hash类型十分贴近对象的数据存储形式,并且可以灵活添加删除对象属性,但hash设计初衷不是为了存储大量对象而设计的,切记不可滥用,更不可以将hash作为对象列表使用
- hgetall 操作可以获取全部属性,如果内部field过多,遍历整体数据效率就会很低,有可能成为数据访问瓶颈
list数据类型
- 存储多个数据,并对数据进入存储空间的顺序进行区分
- 一个存储空间可以保存多个数据,且通过数据可以体现进入顺序
- 保存多个数据,底层使用双向链表存储结构实现
list数据类型基本操作
操作 | 说明 |
---|---|
lpush key value1 [value2] … | 从左边添加/修改数据 |
rpush key value1 [value2] … | 从右边添加/修改数据 |
lrange key start stop | 获取数据 |
lindex key index | 根据指定索引获取值 |
llen key | 获取列表长度 |
lpop key | 从左边获取并移除数据 |
rpop key | 从右边获取并移除数据 |
lrem key count value | 删除指定的数据 |
blpop key1 [key2] timeout | 规定时间内从左边获取并移除数据 |
brpop key1 [key2] timeout | 规定时间内从右边获取并移除数据 |
brpoplpush source destination temeout | 规定时间内获取源列表数据并移除到目的新列表中 |
list数据类型操作注意事项
- list中保存的数据都是string类型的,数据容量是有限的,最多232-1个元素
- list具有索引的概念,但是操作数据时通常以队列的形式进行入队出队操作,或以栈的形式进行入栈出栈操作
- 获取全部数据操作结束索引设置为-1
- list可以对数据进行分页操作,通常第一页的信息来自于list,第二页及更多的信息通过数据库的形式加载
set数据类型
- 存储大量的数据,在查询方面提供更高的效率
- 能够保存大量的数据,高效的内存存储机制,便于查询
- 与hash存储结构完全相同,仅存储键,不存储值 (nil),并且值是不允许重复的
set数据类型的基本操作
操作 | 说明 |
---|---|
sadd key member1 [member2] | 添加数据 |
smembers key | 获取全部数据 |
srem key member1 [member2] | 删除数据 |
scard key | 获取集合数据总量 |
sismember key member | 判断集合中是否包含指定的数据 |
srandmember key [count] | 随机获取集合中指定数量的数据 |
spop key | 随机获取集合中的某个数据并将该数据移除集合 |
sinter key1 [key2 …] | 求两个集合的交集 |
sunion key1 [key2 …] | 求两个集合的并集 |
sdiff key1 [key2 …] | 求两个集合的差集 |
sinterstore destination key1 [key2 …] | 求两个集合的交集并存储到指定的集合中 |
sunionstore destination key1 [key2 …] | 求两个集合的并集并存储到指定的集合中 |
sdiffstore destination key1 [key2 …] | 求两个集合的差集并存储到指定的集合中 |
smove source destination member | 将指定的数据从原始数据集合中移动到目标集合中 |
set数据类型操作的注意事项
- set类型不允许数据重复,如果添加的数据在set中已经存在,将只保留一份
- set虽然与hash的存储结构相同,但是无法启用hash中存储值的空间
key常用指令
key的基本操作
操作 | 说明 |
---|---|
del key | 删除指定的key |
exists key | 获取key是否存在 |
type key | 获取key的类型 |
sort | 排序 |
rename key newkey | 修改名称 |
renamenx key newkey | 判断性修改名称 |
expire key seconds | 为指定的key设置有效期 |
pexpire key milliseconds | 为指定的key设置有效期 |
expireat key timestamp | 为指定的key设置有效期 |
pexpireat key milliseconds-timestamp | 为指定的key设置有效期 |
ttl key | 获取key的有效时间 |
pttl key | 获取key的有效时间 |
persist key | 切换key从时效性转换为永久性 |
keys pattern :查询key
查询规则
规则 | 说明 |
---|---|
* | 匹配任意数量的任意符号 |
? | 配合一个任意符号 |
[] | 匹配一个指定的符号 |
例如:
规则 | 说明 |
---|---|
keys * | 查询所有 |
keys ab* | 查询所有以ab开头 |
keys *me | 查询所有以me结尾 |
keys ??me | 查询所有前面两个字符任意,后面以me结尾 |
keys name:? | 查询所有name:开头,最后一个字符任意 |
keys n[am]? | 查询所有n开头中间包含一个字母a或者m,最后一个字母任意 |
数据库常用指令
- redis为每个服务体哦那个了16个数据库,编号从0到15,每个数据库之间的数据相互独立
操作 | 说明 |
---|---|
move key db | 数据移动 |
dbsize | 数据数量 |
flushdb | 数据清除 |
flushall | 数据清除 |
Jedis
Jedis相关jar包和配置文件下载地址:https://download.csdn.net/download/qq_42795277/12859592
- Jedis是用于Java语言连接redis服务,并且提供对应的操作API
自定义工具类连接Reids
jedis.properties
host=127.0.0.1
port=6379
maxTotal=50
maxIdle=10
utils
package cn.cdw.demo.utils;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
/**
* @author DW-CHEN
*
* JedisPool工具类
* 加载配置文件,配置连接池的参数
* 提供获取连接的方法
*/
public class JedisPoolUtils {
private static JedisPool jedisPool;
static{
InputStream is = JedisPoolUtils.class.getClassLoader().getResourceAsStream("jedis.properties");//读取配置文件
Properties pro = new Properties();
try {
pro.load(is);
} catch (IOException e) {
e.printStackTrace();
}
//获取数据,设置到JedisPoolConfig中
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(Integer.parseInt(pro.getProperty("maxTotal")));//最大活动对象数
config.setMaxIdle(Integer.parseInt(pro.getProperty("maxIdle")));//最大能够保持idel状态的对象数
jedisPool = new JedisPool(config,pro.getProperty("host"),Integer.parseInt(pro.getProperty("port")));//初始化JedisPool
}
public static Jedis getJedis(){//获取连接方法方法
return jedisPool.getResource();
}
}
测试
操作各种类型的数据方式和上面操作redis一样
package cn.cdw.demo;
import cn.cdw.demo.utils.JedisPoolUtils;
import redis.clients.jedis.Jedis;
/**
* @author DW-CHEN
* 使用自定义的连接redis连接池的工具类连接redis
*/
public class Demo1 {
public static void main(String[] args) {
Jedis jedis = JedisPoolUtils.getJedis();
jedis.set("name","小明");
System.out.println(jedis.get("name"));
jedis.close();
}
}
参考:jedis详细配置
#最大活动对象数
redis.pool.maxTotal=1000
#最大能够保持idel状态的对象数
redis.pool.maxIdle=100
#最小能够保持idel状态的对象数
redis.pool.minIdle=50
#当池内没有返回对象时,最大等待时间
redis.pool.maxWaitMillis=10000
#当调用borrow Object方法时,是否进行有效性检查
redis.pool.testOnBorrow=true
#当调用return Object方法时,是否进行有效性检查
redis.pool.testOnReturn=true
#“空闲链接”检测线程,检测的周期,毫秒数。如果为负值,表示不运行“检测线程”。默认为-1.
redis.pool.timeBetweenEvictionRunsMillis=30000
#向调用者输出“链接”对象时,是否检测它的空闲超时;
redis.pool.testWhileIdle=true
# 对于“空闲链接”检测线程而言,每次检测的链接资源的个数。默认为3.
redis.pool.numTestsPerEvictionRun=50
#redis服务器的IP
redis.ip=xxxxxx
#redis服务器的Port
redis1.port=6379
持久化
利用永久性存储介质将数据进行保存,在特定的时间将保存的数据进行恢复的工作机制称为持久化;持久化用于防止数据意外丢失,确保数据安全性
RDB:数据(快照)
- 将当前数据状态进行保存,快照形式,存储数据结果,存储格式简单,关注点在数据
AOF:过程(日志)
- 将数据的操作过程进行保存,日志的形式,存储操作过程,存储格式复杂,关注点在数据操作的过程
RDB
RDB启动方式——save指令
操作 | 说明 |
---|---|
save | 手动执行一次保存操作 |
RDB启动方式——save指令相关配置
操作 | 说明 |
---|---|
dbfilename filename | 设置本地数据库文件名,默认值为dump.rdb,通常设置为dump-端口号.rdb |
dri path | 设置存储.rdb文件的路径,通常设置成存储空间较大的目录中,目录名称为data |
rdbcompression yes|no | 设置存储至本地数据库时是否压缩数据,默认为yes,设置为no,节省CPU运行时间,但存储文件变大 |
rdbchecksum yes|no | 设置读写文件过程是否进行RDB格式校验,默认为yes,设置为no,节约读写10%时间消耗,但存在数据损坏的风险 |
注意:
save指令的执行会阻塞当前Redis服务器,直到当前RDB过程完成为止,有可能会造成长时间阻塞,线上环境不建议使用
RDB启动方式——bgsave指令
操作 | 说明 |
---|---|
bgsave | 手动启动后台保存操作,但不是立即执行 |
RDB启动方式——bgsave指令相关配置
操作 | 说明 |
---|---|
stop-writes-on-bgsave-error yes|no | 后台存储过程中如果出现错误现象,是否停止保存操作,默认为yes |
注意:bgsave命令是针对save阻塞问题做的优化;Redis内部所有涉及到RDB操作都采用bgsave的方式,save命令可以放弃使用
RDB启动方式——save配置
操作 | 说明 |
---|---|
save second changes | 设置自动持久化的条件,满足限定的时间范围内key的变化数量达到指定的数量即进行持久化 |
- second:监控时间范围
- changes:监控key的变化量
注意:save配置要根据实际业务情况进行设置,频度过高或过低都会出现性能问题,结果可能是灾难性的,save配置启动后执行的是bgsave操作
RDB三种启动方式对比
因为RDB启动方式——save配置方式的操作save配置启动后执行的是bgsave操作,所有对比save指令和bgsave指令
方式 | save指令 | bgsave指令 |
---|---|---|
读写 | 同步 | 异步 |
阻塞客户端指令 | 是 | 否 |
额外内存消耗 | 否 | 是 |
启动新进程 | 否 | 是 |
RDB特殊启动形式
操作 | 说明 |
---|---|
debug reload | 服务器运行过程中重启 |
shutdown save | 关闭服务器时指定保存数据 |
RDB优点
- RDB是一个紧凑压缩的二进制文件,存储效率较高
- RDB内部存储的时redis在某个时间点的数据快照,非常适合用于数据备份,全景复制等场景
- RDB恢复数据的速度要比AOF快得多
- 应用:服务器中每X小时执行bgsave备份,并将RDB文件拷贝到远程机器中,用于灾难恢复
RDB缺点
- RDB方式无论是执行指令还是利用配置,无法做到实时持久化,具有较大的可能性丢失数据
- bgsave指令每次运行要执行fork操作创建子进程,要牺牲掉一些性能
- Redis的众多版本中未进行RDB文件格式版本统一,有可能出现各个版本服务之间数据格式无法兼容现象
RDB存储的弊端
- 存储数据量较大,效率较低,基于快照思想,每次读写都是全部数据,当数据量巨大时,效率非常低
- 大数据量下IO性能较低
- 基于fork创建子进程,内存产生额外消耗
- 宕机带来的数据丢失风险
AOF
- AOF(Append Only File)持久化:以独立日志的方式记录每次写命令,重启时在重新执行AOF文件中的命令达到恢复数据的目的;与RDB相比可以简单的理解为 由记录数据改为记录数据产生的变化
- AOF的主要作用时解决了数据持久化的实时性,目前已经是redis持久化的主流方式
启动AOF相关配置
操作 | 说明 |
---|---|
appendonly yes|no | 开启AOF持久化功能,默认为no,即不开启状态 |
appendfilename filename | AOP持久化文件名,默认文件名为appendonly.aof,建议配置为appendonl-端口号.aof |
dir data | AOF持久化文件保存路径,与RDB持久化文件保持一致即可 |
appendfsync always|everysec|no | AOF写数据策略,默认为everysec |
- always(每次):每次写入操作均同步到AOF文件中,数据零误差,性能较低,不建议使用
- everysec(每秒):每秒将缓冲区中的指令同步到AOF文件中,在系统突然宕机的情况下丢失1秒以内的数据;数据准确性较高,性能较高,建议使用,也是默认配置
- no(系统控制):由系统控制每次同步到AOF文件的周期;整体过程不可控
AOF重写方式
操作 | 说明 |
---|---|
bgrewriteaof | 手动重写 |
auto-aof-rewrite-min-size size | 自动重写 |
auto-aof-rewrite-percentage percentage | 自动重写 |
AOF重写作用
- 降低磁盘占用量,提供磁盘利用率
- 提高持久化效率,降低持久化写时间,提高IO性能
- 降低数据恢复复用性,提高数据恢复效率
RDB和AOF对比
持久化方式 | RDB | AOF |
---|---|---|
占用存储空间 | 小(数据级:压缩) | 大(指令级:重写) |
存储速度 | 慢 | 块 |
恢复速度 | 块 | 慢 |
数据安全性 | 会丢失数据 | 依据策略决定 |
资源消耗 | 高/重量级 | 低/轻量级 |
启动优化级 | 低 | 高 |
RDB与AOF的选择之感
对数据非常敏感,建议使用默认的AOF持久化方案
- AOF持久化策略使用everysecond,每秒中fsync一次,该策略redis仍可以保持很好的处理性能,当出现问题时,最多丢失0-1秒内的数据
- 注意:由于AOF文件存储体积较大,且恢复速度较慢
数据呈现阶段有效性,建议使用RDB持久化方案
- 数据可以良好的做到阶段内无丢失(该阶段时开发者或运维人员手工维护的),且恢复速度较快,阶段点数据恢复通常采用RDB方案
综合对比
- RDB与AOF的选择实际上是在做一种权衡,每种都有利和弊
- 如果不能承受分钟以内的数据丢失,对业务非常敏感,选用AOF
- 如果能承受分钟以内的数据丢失,且追求大数据的恢复速度,选用RDB
- 灾难恢复选用RDB
- 双保险策略,同时开启RDB与AOF,重启后,Redis优先使用AOF来恢复数据,降低丢失数据量