导图社区 Redis
这是一篇关于Redis的思维导图,介绍详细,描述全面,希望对感兴趣的小伙伴有所帮助!
编辑于2023-12-21 17:36:42Redis
事务
定义
事务是一个单独的隔离操作,事务中的所有操作都将序列化,有顺序的执行,事务执行的过程中不会被其他客服端发来的命令打断
作用
串联多个命令防止其他命令插队
命令
WATCH key [key ...]
在执行multi之前,先执行watch key1 [key2],可以监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。
Multi
输入的命令都会进入命令队列,但是不会执行,将等待Exec命令执行,然后依次执行
Exec
执行命令队列
discard
丢弃命令队列
事务的错误处理
组队成功,执行成功,所有的命令都将有序执行
组队成功,选择discard,所有的命令都不会执行
组队中某个命令出错,执行时整个队列的命令都会被取消
组队成功,执行时某个命令出错,除了出错的命令,其他的命令都将执行
Redis事务没有原子性
Redis事务的三大特性
单独的隔离操作
事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
没有隔离级别的概念
队列中的命令没有提交之前都不会实际被执行,因为事务提交前任何指令都不会被实际执行
不保证原子性
事务中如果有一条命令执行失败,其后的命令仍然会被执行,没有回滚
Redis事务与Mysql事务的区别(围绕ACID)

持久化
RDB
核心配置
保存路径:默认在启动目录下 可以通过修改配置文件更改路径
dbfilename 配置文件名称

save

多少秒内进行了多少次操作
触发RDB
自动触发save
会阻塞主进程,直到完成RDB持久化
手动保存: bgsave
Redis会在后台异步进行快照操作, 快照同时还可以响应客户端请求。
通过lastsave可以获取最后一次执行快照的时间
不会阻塞主进程
执行flushall命令
执行flushall命令,也会产生dump.rdb文件,但里面是空的,没有意义
flushdb命令不会产生dump.rdb文件
正常退出Redis
redis.conf中更多配置
stop-writes-on-bgsave-error
当Redis无法写入磁盘的话,直接关掉Redis的写操作。推荐yes
rdbcompression 压缩文件
如果你不想消耗CPU来进行压缩的话,可以设置为关闭此功能。推荐yes.
rdbchecksum 检查完整性
在存储快照后,还可以让redis使用CRC64算法来进行数据校验
持久化流程(内存快照)
Redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入到 一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。 整个过程中,主进程是不进行任何IO操作的,这就确保了极高的性能 如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。RDB的缺点是最后一次持久化后的数据可能丢失
Fork的作用是复制一个与当前进程一样的进程。新进程的所有数据(变量、环境变量、程序计数器等) 数值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程
优势
适合大规模的数据恢复
对数据完整性和一致性要求不高更适用
节省磁盘空间
恢复速度快
劣势
可能会丢失最后一次快照所有的修改
AOF
介绍
以日志的形式记录每一次写操作,只可以追加文件但不能改写文件
默认不开启
appendonly no
AOF和RDB同时开启会优先选择AOF
持久化流程
客户端的请求写命令会被追加到AOF缓冲区
AOF缓冲区根据AOF持久化策略将操作同步到磁盘的AOF文件中
AOF文件超过重写策略或手动重写时,会对AOF文件rewrite重写,压缩AOF文件容量
Redis服务器重启时,会load加载AOF文件中的写操作
同步频率设置
appendfsync always
始终同步,每次Redis的写入都会立刻记入日志;性能较差但数据完整性比较好
appendfsync everysec
每秒同步,先将日志写到AOF文件的内存缓冲区,每隔一秒再把缓冲区的内容写入磁盘,如果宕机,本秒的数据可能丢失
appendfsync no
redis不主动进行同步,把同步时机交给操作系统。
优势
备份机制更稳健,数据不容易丢失
可读的日志文件,可以处理错误操作
劣势
比RDB占用更多的磁盘空间
恢复速度慢
每次都进行读写同步的话,性能有压力
存在个别bug,造成不能恢复
Redis过期键删除策略
Redis采用的是定期删除和惰性删除两种结合的策略
定期删除:每隔一段时间,随机抽取设置了过期时间的key,检查是否过期,过期删除
每1秒重复10次,随机抽取20个key检查是否过期,如果25%的key过期了,就重复该行为
会漏掉很多的过期键
惰性删除:数据过期时,先不处理,当过期键被访问时,在进行删除
用空间换时间
如果漏掉了很多的过期键,并且没有去检查,也就不会走惰性删除,大量的过期键堆积在内存中,导致Redis内存耗尽,此时就要走内存淘汰机制
主从复制
是什么
主机数据更新后,根据策略,自动将数据同步到master/slave机制.master负责写,slave负责读
能干嘛
读写分离,性能扩展
容灾快速恢复,提高可用性
怎么玩
启动多个redis服务
配置从库
执行 slaveof IP port
查询主从信息
info replication
常见情况
一主二仆
从机是否可以写?set可否?
不可以写,set也不行
主机shutdown后情况如何?从机是上位还是原地待命?
从机原地待命
主机又回来了后,主机新增记录,从机还能否顺利复制?
可以
其中一台从机down后情况如何?依照原有它能跟上大部队吗?
可以
薪火相传
master和slave双重身份的机器是否可以写数据呢??
不可以,只要有从机的身份,就不能写数据
反客为主
主机宕机了,可以手动使从机变为主机
复制原理
slave启动成功连接到master后会发送一个sync命令
Master接到命令启动后台的存盘进程,同时收集所有接收到的用于修改数据集命令, 在后台进程执行完毕之后,master将传送整个RDB数据文件到slave,以完成一次完全同步
全量复制:而slave服务在接收到数据库文件数据后,将其存盘并加载到内存中。
增量复制:Master继续将新的所有收集到的修改命令依次传给slave,完成同步
但是只要是重新连接master,一次完全同步(全量复制)将被自动执行
哨兵模式
哨兵就是一个运行在特性模式下的Redi进程,主要有三个任务
监控
给所有的主从库发送PING命令,检查是否存活,没有在规定的时间内响应判定为下线
主观下线
如果哨兵发现主库或从库对 PING 命令的响应超时了,那么,当前哨兵就会先把它标记 为“主观下线
客观下线
如果 N/2+1 的哨兵都将该主库标记为主观下线,那么该主库就会被标记为 "客观下线"
只有主库被标记为客观下线,哨兵才会去选举新的主库
如果只有一个哨兵,当因为网络原因或者主库压力过大,主库没有及时响应哨兵,被哨兵标记为主观下线,而此时又只有一个哨兵,将直接选举新的主库 而如果有哨兵集群,必须要N/2+1以上的哨兵标记主库为主观下线,主库才会被标记为客观下线,哨兵才会去选举新的主库 能减少误判
选主
主库挂了将在从机中选出新的主库
选举新的主库过程
筛选
从库的当前在线状态,还要判断它之前的网络连接状态
打分
从库优先级
从库复制进度
从库ID号
通知
将新的主库信息发送给其他的从库,让其他的从库和新的主库建立连接,进行数据复制
是什么
反客为主的自动版,能够后台监控主机是否故障,如果故障了根据投票数自动将从库转换为主库
怎么玩
新建sentinel.conf文件,名字绝不能错
配置哨兵,填写内容
sentinel monitor mymaster 127.0.0.1 6379 1
其中mymaster为监控对象起的服务器名称, 1 为至少有多少个哨兵同意迁移的数量。
启动哨兵
/usr/local/bin
执行redis-sentinel /myredis/sentinel.conf
当主机挂掉,将在从机中选新的主机
选举规则
优先级
在redis.conf中默认:replica-priority 100,值越小优先级越高
偏移量
偏移量是指获得原主机数据最全的
runid
每个redis实例启动后都会随机生成一个40位的runid(通过info server获取查看)
集群
什么是集群
对Redis的水平扩容
集群中有一部分节点失效或者无法进行通讯, 集群也可以继续处理命令请求。
主机宕机,从机自动提升为Master
配置
redis cluster配置修改
cluster-enabled yes 打开集群模式
cluster-config-file nodes-6379.conf 设定节点配置文件名
cluster-node-timeout 15000 设定节点失联时间,超过该时间(毫秒),集群自动进行主从切换。
启动
redis-cli --cluster create --cluster-replicas 1 192.168.11.101:6379 192.168.11.101:6380 192.168.11.101:6381 192.168.11.101:6389 192.168.11.101:6390 192.168.11.101:6391
不要用127.0.0.1, 请用真实IP地址
什么是slots
一个 Redis 集群包含 16384 个插槽(hash slot), 数据库中的每个键都属于这 16384 个插槽的其中一个
不在一个slot下的键值,是不能使用mget,mset等多键操作。
集群的不足
多键操作是不被支持的
多键的Redis事务是不被支持的。lua脚本不被支持
复杂度较大
为什么集群需要至少三个节点
一个节点挂了,有一半以上的节点通过ping-pong方式的投票机制认为它挂了,那么这个集群就挂了.如果只有两个节点,一个节点挂了,另外一个节点投票.只有50%,不过半数,这个集群就不会挂,所以至少需要三个节点
为什么集群至少需要六台服务器
因为一个集群至少需要三个节点,而每一个节点需要一个备份机,所以一个集群需要至少六台服务器
JAVA连接开发 Jedis
依赖: <artifactId>jedis</artifactId>
JedisPool 连接池
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"> <property name="maxTotal" value="100"/> <property name="maxIdle" value="100"/> <property name="testOnBorrow" value="true"/> <property name="testOnReturn" value="true"/> </bean> <bean id="jedisPool" class="redis.clients.jedis.JedisPool"> <constructor-arg name="poolConfig" ref="jedisPoolConfig" /> <constructor-arg name="host" value="192.168.11.222" /> <constructor-arg name="port" value="6379" type="int" /> <constructor-arg name="timeout" value="30000" type="int" /> </bean>

setBlockWhenExhausted
/连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true
setTestOnBorrow
从连接池中取连接的时候检查是否失活
自动装配JedisPool对象
@Autowired private JedisPool jedisPool;
五大数据类型
应用

基本使用
安装目录
/usr/local/bin
redis-benchmark:性能测试工具,可以在自己本子运行,看看自己本子性能如何
redis-check-aof:修复有问题的AOF文件,rdb和aof后面讲
redis-check-dump:修复有问题的dump.rdb文件
redis-sentinel:Redis集群使用
redis-server:Redis服务器启动命令
redis-cli:客户端,操作入口
配置文件 redis.conf
后台启动
daemonize no 改成 yes
启动服务器 redis-server /myredis/redis.conf
用客户端访问 redis-cli
-p 指定端口
-c 集群方式
网络相关配置
bind
默认只接受本机访问
不写即无限制接受所有的IP地址的访问
protected-mode保护模式
默认开启 即使接受所有IP地址的访问,也不能访问成功

Port 端口号
默认 6379
tcp-backlog 连接队列

timeout 超时时间
一个空闲的客户端多久会关闭 0关闭该功能 即永远不断开连接
tcp-keepalive 对客户端的心跳检测
设置为0即不会进行keepalive检测
通用配置
daemonize 守护线程
默认 no 设置为yes是守护进程,可以后台启动
pidfile 存放pid文件的位置
loglevel 日记的级别
debug:会打印生成大量信息,适用于开发/测试阶段
verbose:包含很多不太有用的信息,但是不像debug级别那么混乱
notice:适度冗长,适用于生产环境
warning:仅记录非常重要、关键的警告消息
logfile 日志文件名称
默认是 logfile stdout
databases 设置数据库的数量
默认数据库数量是16 默认选择数据库是0
限制
maxclients 最大服务器连接数
默认1W个连接,达到上限将拒绝连接
maxmemory
建议必须设置,否则,将内存占满,造成服务器宕机
maxmemory-policy 内存淘汰策略
volatile-lru:使用LRU算法移除key,只对设置过期时间的键;(最近最少使用)
volatile-ttl:移除那些TTL值最小的key,即那些最近要过期的key
volatile-random:在过期集合中移除随机的key,只对设置了过期时间的键
allkeys-lru:在所有集合key中,使用LRU算法移除key
allkeys-random:在所有集合key中,移除随机的key
noeviction:不进行移除。针对写操作,只是返回错误信息

设置内存淘汰策略注意 用横杠,不能用下划线 
IO限制
io-threads-do-reads 是否开启IO多线程
默认no,如果开启,修改为yes
io-threads IO线程数量
4核的机器建议设置为 2 或 3 个线程,8 核的建议设置为 6 个线程,线程数一定要小于机器核数,尽量不超过8个
Redis关闭
单实例关闭
redis-cli shutdown
多实例关闭
redis-cli -p 6379 shutdown
单线程+多路IO复用

Redis6.0引入了多线程
NoSQL数据库
什么是NoSQL数据库
不遵循SQL标准
不支持ACID
原子性
一致性
隔离性
持久性
远超SQL的性能
适用场景
对数据高并发的读写
海量数据的读写
对数据高扩展性的
不使用场景
需要事务支持
需要结构化查询存储,处理复杂关系,需要即席查询
即席查询:用户根据自己的需求,灵活的选择查询条件,系统根据用户的选择生成相应的统计报表
Redis五大数据类型
String类型
增
set <key><value>添加键值对
setex <key><过期时间><value> 设置键值的同时,设置过期时间,单位秒。
setnx <key><value>只有在 key 不存在时 设置 key 的值
mset <key1><value1><key2><value2>同时设置一个或多个 key-value对
查
get <key>查询对应键值
strlen <key>获得值的长度
mget <key1><key2><key3> 同时获取一个或多个 value
getrange <key><起始位置><结束位置> 获得值的范围,类似java中的substring,前包,后包
改
incr <key>
将 key 中储存的数字值增1
只能对数字值操作,如果为空,新增值为1
decr <key>
将 key 中储存的数字值减1
只能对数字值操作,如果为空,新增值为-1
incrby / decrby <key><步长>将 key 中储存的数字值增减。自定义步长。
删
del key
特殊
append <key><value>将给定的<value> 追加到原值的末尾
getset <key><value>
以新换旧,设置了新值同时获得旧值
商品编号、订单号采用string的递增数字特性生成。
List类型
增
lpush/rpush <key><value1><value2><value3> .... 从左边/右边插入一个或多个值。
查
lrange <key><start><stop>
按照索引下标获得元素(从左到右)
lindex <key><index>按照索引下标获得元素(从左到右)
llen <key>获得列表长度
改
lset<key><index><value>将列表key下标为index的值替换成value
删
lrem <key><n><value>从左边删除n个与value相等的元素(从左到右)
特殊
lpop/rpop <key>从左边/右边吐出一个值。值在键在,值光键亡。
rpoplpush <key1> <key2>从<key1>列表右边吐出一个值,插到<key2>列表左边。
linsert <key> before <value><newvalue>在<value>的后面插入<newvalue>插入值
如好友列表,粉丝列表,消息队列,最新消息排行等。 rpush方法就相当于将消息放入到队列中,lpop/rpop就相当于从队列中拿去消息进行消费
Hash类型
增
hset <key><field><value>给<key>集合中的 <field>键赋值<value>
hmset <key1><field1><value1><field2><value2>... 批量设置hash的值
查
hget <key1><field>从<key1>集合<field>取出 value
hmget <key1><field1> <field2>... 批量获取hash的值
hlen <key> 获取hash中field-value的数量
hexists<key1><field>查看哈希表 key 中,给定域 field 是否存在
改
hincrby <key><field><increment>为哈希表 key 中的域 field 的值加上增量 (为负既是减去)
hsetnx <key><field><value>将哈希表 key 中的域 field 的值设置为 value ,当且仅当域 field 不存在
删
hdel <key><field> 删除<key>集合中指定<field>
特殊
hgetall <key> 获取中所有的field和value
hkeys <key>列出该hash集合的所有field
hvals <key>列出该hash集合的所有value
用一个对象来存储用户信息,商品信息,订单信息等等
ZSet类型
增
zadd <key><score1><member 1><score2><member 2>…
将一个或多个 member 元素及其 score 值加入到有序集 key 当中
查
zcard<key>返回该有序集合的元素个数
zcount <key><min><max>统计该集合,分数区间内的元素个数
zrange <key><start><stop> [WITHSCORES] 从小到大排序
返回有序集 key 中,下标在<start><stop>之间的元素
带WITHSCORES,可以让分数一起和值返回到结果集
zrevrange <key><start><stop> [WITHSCORES] 从大到小排序
zrangebyscore key min max [withscores] [limit offset count]
返回有序集 key 中,所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员。有序集成员按 score 值递增(从小到大)次序排列。
zrevrangebyscore key max min [withscores] [limit offset count] (注意参数 是 大 小)
同上,改为从大到小排列。
zrank <key><member > 返回有序集 key 中成员member 的排名。其中有序集成员按 score 值递增(从小到大)顺序排列。排名以 0 为底,也就是说, score 值最小的成员排名为 0 。
zrevrank <key><member > 获得成员按 score 值递减(从大到小)排列的排名。
改
zincrby <key><increment><member > 为元素的score加上增量
删
zrem <key><member >删除该集合下,指定值的元素
特殊
排行榜:例如视频网站需要对用户上传的视频做排行榜.
Set类型
增
sadd <key><value1><value2> .....
将一个或多个 member 元素加入到集合 key 中,已经存在的 member 元素将被忽略
查
smembers <key>取出该集合的所有值
scard<key>返回该集合的元素个数
ismember<key> <value> 查询集合中值是否已经存在
改
删
srem <key><value1><value2> .... 删除集合中的某个元素
特殊
spop <key>随机从该集合中吐出一个值
smove <source><destination>value把集合中一个值从一个集合移动到另一个集合
sinter <key1><key2>返回两个集合的交集元素。
sunion <key1><key2>返回两个集合的并集元素。
sdiff <key1><key2>返回两个集合的差集元素(key1中的,不包含key2中的)
投票记录 共同好友、共同兴趣、分类标签