Redis非关系型数据库学习笔记--更新中

NoSql(Not Only Sql)非关系型数据库

这类型数据存储不需要固定的模式,key-value cache persistent存储
易扩展
把反复查询的数据放到缓存里,减少过多查询数据库
读写分离:写(主数据库),读(副数据库)
表锁,行锁(高并发下使用时把数据锁起来,一次只能一个使用)
分表分库:减小数据库压力
无需事先创建对应字段,灵活性高

出现原因:关系型数据库无法解决过于复杂的关系(例如亲戚)
高并发、高可扩、高性能

BSONBinary JSON

聚合模型:

  1. KV键值(Redis)
  2. 文档型数据库 BSON(CacheDb、MongoDB)
  3. 列族
  4. 图形(朋友圈社交网络、广告推荐系统)

CAP:(三进二)

  • C:Consistency 强一致性
  • A:可用性
  • P:分区容忍性

Redis(很高效)
一个基于内存的单线程高性能key-value型数据库(NoSql),读写性能优越,支持多种数据类型(list、set、zset、hash),master-slaver数据备份
epoll(linux内核),多路io复用,读写快
内存储存和持久化:异步将内存数据写到硬盘上
CONFIG命令获取和设置所有的Redis配置。


命令:
select 获取数据库(0-15)
get key 获取key
set key value 设置键值
DSBSIZE 当前表容量
FLUSHDB、FLUSHALL清空当前库和所有库
exists key 存在key(1) 没有(0)
ttl 过期时间(-1永不过期 -2 已经过期)
expire key time(设置过期时间)


数据类型

哈希(hash)
String类型的field和value的映射表,hash特别适合用于存储对象

redis 127.0.0.1:6379> HMSET user:1 username
OK
redis 127.0.0.1:6379> HGETALL user:1
1) "username"

列表(list)
列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素导列表的头部(左边)或者尾部(右边)。

redis 127.0.0.1:6379> lpush redis.net.cn redis
(integer) 1
redis 127.0.0.1:6379> lrange redis.net.cn 0 10

集合(set)
Set是string类型的无序无重复集合。
集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。

redis 127.0.0.1:6379> sadd redis.net.cn redis
(integer) 1
redis 127.0.0.1:6379> smembers redis.net.cn

有序集合(zset):sorted set
通过分数来为集合中的成员进行从小到大的排序。

redis 127.0.0.1:6379> zadd redis.net.cn 0 redis
(integer) 1
redis 127.0.0.1:6379> zadd redis.net.cn 0 rabitmq
(integer) 1
redis 127.0.0.1:6379> zadd redis.net.cn 0 rabitmq
(integer) 0
redis 127.0.0.1:6379> ZRANGEBYSCORE redis.net.cn 0 1000

Redis持久化

为了让数据在Redis重启后还可用,Redis提供了两种rdbaof持久化机制。

RDB

rdb:redis Database
将redis存储的数据生成快照snapshot并存储到磁盘等介质上
对于RDB方式,redis会单独创建(fork)一个子进程来进行持久化,而主进程是不会进行任何IO操作的,这样就确保了redis极高的性能。
redis在进行数据持久化的过程中,会先将数据写入到一个临时文件中,待持久化过程都结束了,才会用这个临时文件替换上次持久化好的文件。

rdb核心就是:rdbSave和rdbLoad函数,前者用于生成RDB文件到磁盘,后者用于将磁盘文件加载到内存中。

保存

  • SAVE:直接调用rdbSave,阻塞主线程,直到保存完成,阻塞期间,服务器不能处理客户端任何请求。
  • BGSAVE:fork出一个子线程,负责调用rdbSave,保存完成发送信号给主线程,主线程在期间可以处理客户端请求。

BGSAVE执行期间不能执行SAVE,避免执行两个rdbSave,造成条件竞争。

载入

当Redis服务器启动时,rdbLoad执行,读取RDB文件,写入内存中。

aof保存频率比rdb高,所以一半aof文件数据比rdb数据更新。

AOF

aof:append only file
以日志记录形式写操作,只能追不能改写
AOF方式是将执行过的写指令记录下来,在数据恢复时按照从前到后的顺序再将指令都执行一遍使用Queue,就这么简单。

AOF方式的另一个好处,我们通过一个“场景再现”来说明。某同学在操作redis时,不小心执行了FLUSHALL,导致redis内存中的数据全部被清空了,这是很悲剧的事情。不过这也不是世界末日,只要redis配置了AOF持久化方式,且AOF文件还没有被重写(rewrite),我们就可以用最快的速度暂停redis并编辑AOF文件,将最后一行的FLUSHALL命令删除,然后重启redis,就可以恢复redis的所有数据到FLUSHALL之前的状态了。是不是很神奇,这就是AOF持久化方式的好处之一。但是如果AOF文件已经被重写了,那就无法通过这种方法来恢复数据了。

AOF 文件写入过程

  1. 命令传播:Redis 将执行完的命令、命令的参数、命令的参数个数等信息发送到 AOF 程序中。
  2. 缓存追加:AOF 程序根据接收到的命令数据,将命令转换为网络通讯协议的格式,然后将协议内容追加到服务器的 AOF 缓存中。(追加到redisServer的aof_buf)
  3. 文件写入和保存:AOF 缓存中的内容被写入到 AOF 文件末尾,如果设定的 AOF 保存条件被满足的话,fsync 函数或者 fdatasync 函数会被调用,将写入的内容真正地保存到磁盘中。

WRITER:将aof_buf写入AOF文件

SAVE:将AOF文件写入磁盘

AOF保存模式

  • AOF_FSYNC_NO 不保存:SAVE不执行
  • AOF_FSYNC_EVERYSEC 每一秒钟保存一次:SAVE由子线程调用,不阻塞服务器主进程
  • AOF_FSYNC_ALWAYS 执行一个命令保存一次:SAVE由服务器主进程执行,会阻塞
模式 WRITE 是否阻塞? SAVE 是否阻塞? 停机时丢失的数据量
AOF_FSYNC_NO 阻塞 阻塞 操作系统最后一次对 AOF 文件触发 SAVE 操作之后的数据。
AOF_FSYNC_EVERYSEC 阻塞 不阻塞 一般情况下不超过 2 秒钟的数据。
AOF_FSYNC_ALWAYS 阻塞 阻塞 最多只丢失一个命令的数据。

AOF重写

因为采用了追加方式,如果不做任何处理的话,AOF文件会变得越来越大,为此,redis提供了AOF文件重写(rewrite)机制,即当AOF文件的大小超过所设定的阈值时,redis就会启动AOF文件的内容压缩,只保留可以恢复数据的最小指令集

即:

使用lpush list 1 2 3

代替

lpush list 1

lpush list 2

lpush list 3

1、在重写即将开始之际,redis会创建(fork)一个“重写子进程”,这个子进程会首先读取现有的AOF文件,并将其包含的指令进行分析压缩并写入到一个临时文件中。(使用子线程重写是为了期间Redis主进程可以处理客户端请求)

2、与此同时,主工作进程会将新接收到的写指令一边累积到内存缓冲区中,一边继续写入到原有的AOF文件中,这样做是保证原有的AOF文件的可用性,避免在重写过程中出现意外。(使用缓冲区是防止重写时Redis处理新的请求使得数据更新)

3、当“重写子进程”完成重写工作后,它会给父进程发一个信号,父进程收到信号后就会将内存中缓存的写指令追加到新AOF文件中。

4、当追加结束后,redis就会用新AOF文件来代替旧AOF文件,之后再有新的写指令,就都会追加到新的AOF文件中了。

AOF和RDB比较

  • 官方的建议是两个同时使用。这样可以提供更可靠的持久化方案
  • RDB需要定时持久化,风险是可能会丢两次持久之间的数据,量可能很大。
  • 在同样数据规模的情况下,AOF文件要比RDB文件的体积大。而且,AOF方式的恢复速度也要慢于RDB方式。

Redis事务

一次执行多个命令,批处理(一起成功、一起失败)
在这里插入图片描述

redis 127.0.0.1:6379> MULTI 
OK 
redis 127.0.0.1:6379> SET mykey "redis" 
QUEUED 
redis 127.0.0.1:6379> GET mykey 
QUEUED 
redis 127.0.0.1:6379> INCR visitors 
QUEUED 
redis 127.0.0.1:6379> EXEC  
1) OK 
2) "redis" 
3) (integer) 1

watch类似乐观锁

//balance100 debt 20
127.0.0.1:6379> watch balance
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> DECRBY balance 20
QUEUED
127.0.0.1:6379> INCRBY debt 20
QUEUED
127.0.0.1:6379> EXEC
1) (integer) 80
2) (integer) 40
  • 本文作者: dzou | 微信:17856530567
  • 本文链接: http://www.dzou.top/post/7c806d9b.html
  • 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!
  • 并保留本声明和上方二维码。感谢您的阅读和支持!