Redis简述

NoSQL数据库简介

技术发展

Redis简述_第1张图片

Web1.0时代

Redis简述_第2张图片

Web2.0时代

Redis简述_第3张图片

解决CPU及内存压力

Redis简述_第4张图片

解决IO压力

Redis简述_第5张图片

NoSQL数据库

NoSQL数据库概述

NoSQL(NoSQL = Not Only SQL ),意即“不仅仅是SQL”,泛指 非关系型的数据库

NoSQL 不依赖业务逻辑方式存储,而以简单的key-value模式存储。因此大大的增加了数据库的扩展能力。

  • 不遵循SQL标准。
  • 不支持ACID。
  • 远超于SQL的性能。

NoSQL适用场景

  • 对数据高并发的读写
  • 海量数据的读写
  • 对数据高可扩展性的

NoSQL不适用场景

  • 需要事务支持
  • 基于sql的结构化查询存储,处理复杂的关系,需要即席查询。
  • 用不着sql的和用了sql也不行的情况,请考虑用NoSql

Redis概述

  • Redis是一个开源的key-value存储系统。
  • 支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。
  • 这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。
  • Redis支持各种不同方式的排序。
  • 为了保证效率,数据都是缓存在内存中。
  • Redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件。
  • 并且在此基础上实现了master-slave(主从)同步。

应用场景

配合关系型数据库做高速缓存

  • 高频次,热门访问的数据,降低数据库IO
  • 分布式架构,做session共享

Redis简述_第6张图片

多样的数据结构存储持久化数据

Redis简述_第7张图片

常用五大数据类型简介

Redis (key)

命令 描述
keys * 查询当前库所有的Key
exists key 查看某个key是否存在
type key 查看key是什么类型
del key 删除指定key数据
expire key 10 10秒钟:为给定的key设置过期时间
ttl key 查看还有多少秒过期,-1标识永不过期,-2标识已过期
select 命令切换数据库
dbsize 查看当前数据库的key的数量
flushdb 清空当前库
flushall 通杀全部库

Redis 字符串 (String)

String是Redis最基本的类型,可以理解成与Memcached一模一样的类型,一个key对应一个value。

String类型是二进制安全的。意味着Redis的string可以包含任何数据。比如jpg图片或者序列化的对象。

String类型是Redis最基本的数据类型,一个Redis中字符串value最多可以是512M

命令 描述
set 添加键值对
get 查询对应键值
append 将给定的 追加到原值的末尾
strlen 获得值的长度
setnx 只有在 key 不存在时  设置 key 的值
incr 将 key 中储存的数字值增1,只能对数字值操作,如果为空,新增值为1
decr 将 key 中储存的数字值减1,只能对数字值操作,如果为空,新增值为-1
incrby / decrby  <步长> 将 key 中储存的数字值增减。自定义步长

Redis 列表 (List)

单键多值

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

它的底层实际是个双向链表,对两端的操作性能很高,通过索引下标的操作中间的节点性能会较差。

image.png

命令 描述
lpush/rpush       … 从左边/右边插入一个或多个值
lpop/rpop 从左边/右边吐出一个值。值在键在,值光键亡
rpoplpush 从列表右边吐出一个值,插到列表左边
lrange 按照索引下标获得元素(从左到右):lrange mylist 0 -1>从0开始,-1表示获取所有
lindex 按照索引下标获得元素(从左到右)
llen 获得列表长度
linsert  before 在的后面插入 插入值
lrem 从左边删除n个value(从左到右)

Redis 集合 (Set)

Redis set对外提供的功能与list类似是一个列表的功能,特殊之处在于set是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。

Redis的Set是string类型的无序集合。它底层其实是一个value为null的hash表,所以添加,删除,查找的 复杂度都是O(1)

一个算法,随着数据的增加,执行时间的长短,如果是O(1),数据增加,查找数据的时间不变

命令 描述
sadd     … 将一个或多个 member 元素加入到集合 key 中,已经存在的 member 元素将被忽略
smembers 取出该集合的所有值
sismember 判断集合是否为含有该值,有1,没有0
scard 返回该集合的元素个数
srem … 删除集合中的某个元素
spop 随机从该集合中吐出一个值
srandmember 随机从该集合中取出n个值。不会从集合中删除
sinter 返回两个集合的交集元素
sunion 返回两个集合的并集元素
sdiff 返回两个集合的差集元素(key1中的,不包含key2中的)

Redis 哈希 (Hash)

Redis hash 是一个键值对集合。

Redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象。

类似Java里面的Map

用户ID为查找的key,存储的value用户对象包含姓名,年龄,生日等信息,如果用普通的key/value结构来存储

主要有以下2种存储方式:

Redis简述_第8张图片 Redis简述_第9张图片
每次修改用户的某个属性需要,
先反序列化改好后再序列化回去。开销较大。 用户ID数据冗余
Redis简述_第10张图片 col1
通过 key(用户 ID) + field( 属性标签 ) 就可以操作对应属性数据了,既不需要重复存储数据,也不会带来序列化和并发修改控制的问题
命令 描述
hset 给集合中的  键赋值
hget 从集合 取出 value
hmset   … 批量设置hash的值
hexists 查看哈希表 key 中,给定域 field 是否存在
hkeys 列出该hash集合的所有field
hvals 列出该hash集合的所有value
hincrby 为哈希表 key 中的域 field 的值加上增量 1
hsetnx 将哈希表 key 中的域 field 的值设置为 value ,当且仅当域 field 不存在

Redis有序集合Zset(sorted set)

Redis有序集合zset与普通集合set非常相似,是一个没有重复元素的字符串集合。

不同之处是有序集合的每个成员都关联了一个 评分(score) ,这个评分(score)被用来按照从最低分到最高分的方式排序集合中的成员。集合的成员是唯一的,但是评分可以是重复了 。

因为元素是有序的, 所以你也可以很快的根据评分(score)或者次序(position)来获取一个范围的元素。

访问有序集合的中间元素也是非常快的,因此你能够使用有序集合作为一个没有重复成员的智能列表。

命令 描述
zadd   … 一个或多个 member 元素及其 score 值加入到有序集 key 当中
zrange    [WITHSCORES] 返回有序集 key 中,下标在 之间的元素
带WITHSCORES,可以让分数一起和值返回到结果集
zrangebyscore   [withscores] [limit offset count] 返回有序集 key 中,所有 score 值介于 min 和 max 之间(包
括等于 min 或 max )的成员
有序集成员按 score 值递增(从小到大)次序排列
zrevrangebyscore key max min [withscores] [limit offset count] 返回有序集 key 中,所有 score 值介于 min 和 max 之间(
包括等于 min 或 max )的成员。
有序集成员按 score 值递增(从大到小)次序排列
zincrby 为元素的score加上增量
zrem 删除该集合下,指定值的元素
zcount 统计该集合,分数区间内的元素个数
zrank 返回该值在集合中的排名,从0开始

Redis配置文件介绍

bind

默认情况bind=127.0.0.1只能接受本机的访问,请求不写的情况下,无限制接受任何ip地址的访问

生产环境肯定要写应用服务器的地址;服务器是需要远程访问的,所以需要将其注释掉

如果开启了protected-mode,那么在没有设定bind ip且没有设密码的情况下,Redis只允许接受本机的相应

protected-mode

本机访问保护模式设置

port

端口号,默认 6379

tcp-backlog

设置tcp的backlog,backlog其实是一个连接队列,backlog队列总和=未完成三次握手队列 + 已经完成三次握手队列。

在高并发环境下需要一个高backlog值来避免慢客户端连接问题。

timeout

一个空闲的客户端维持多少秒会关闭,0表示关闭该功能。即永不关闭

tcp-keepalive

对访问客户端的一种心跳检测,每个n秒检测一次。

单位为秒,如果设置为0,则不会进行Keepalive检测

daemonize

是否为后台进程,设置为yes守护进程,后台启动

pidfile

存放pid文件的位置,每个实例会产生一个不同的pid文件

loglevel

指定日志记录级别,Redis总共支持四个级别:debug、verbose、notice、warning,默认为notice

logfile

日志文件名称

databases

设定库的数量 默认16,默认数据库为0,可以使用SELECT 命令在连接上指定数据库id

Redis事务

事务定义

Redis事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。

Redis事务的主要作用就是串联多个命令防止别的命令插队。

Multi、Exec、discard

从输入Multi命令开始,输入的命令都会依次进入命令队列中,但不会执行,直到输入Exec后,Redis会将之前的命令队列中的命令依次执行。

组队的过程中可以通过discard来放弃组队。

事务的错误处理

组队中某个命令出现了报告错误,执行时整个的所有队列都会被取消。

Redis简述_第11张图片

如果执行阶段某个命令报出了错误,则只有报错的命令不会被执行,而其他的命令都会执行,不会回滚。

Redis简述_第12张图片

悲观锁

悲观锁(Pessimistic Lock) , 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。 传统的关系型数据库里边就用到了很多这种锁机制 ,比如 行锁表锁等, 读锁写锁等,都是在做操作之前先上锁。

乐观锁

乐观锁(Optimistic Lock) , 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。 乐观锁适用于多读的应用类型,这样可以提高吞吐量 。Redis就是利用这种check-and-set机制实现事务的。

watch key

在执行multi之前,先执行watch key1 [key2],可以监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。

unwatch

取消 WATCH 命令对所有 key 的监视。

如果在执行 WATCH 命令之后, EXEC 命令或 DISCARD 命令先被执行了的话,那么就不需要再执行 UNWATCH 了。

Redis事务三特性

  • 单独的隔离操作

  • 事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。

  • 没有隔离级别的概念

  • 队列中的命令没有提交之前都不会实际被执行,因为事务提交前任何指令都不会被实际执行

  • 不保证原子性

  • 事务中如果有一条命令执行失败,其后的命令仍然会被执行,没有回滚

Redis持久化之RDB

RDB简介

在指定的时间间隔内将内存中的数据集快照写入磁盘, 也就是行话讲的Snapshot快照,它恢复时是将快照文件直接读到内存里

备份是如何执行的

Redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入到 一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。 整个过程中,主进程是不进行任何IO操作的,这就确保了极高的性能 如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。RDB的缺点是 最后一次持久化后的数据可能丢失

Fork

  • Fork的作用是复制一个与当前进程一样的进程。新进程的所有数据(变量、环境变量、程序计数器等) 数值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程
  • 在Linux程序中,fork()会产生一个和父进程完全相同的子进程,但子进程在此后多会exec系统调用,出于效率考虑,Linux中引入了“ 写时复制技术
  • 一般情况父进程和子进程会共用同一段物理内存 ,只有进程空间的各段的内容要发生变化时,才会将父进程的内容复制一份给子进程。

dump.rdb文件

快照保存文件,在redis.conf中配置文件名称,默认为dump.rdb

image.png

优势

  • 适合大规模的数据恢复
  • 对数据完整性和一致性要求不高更适合使用
  • 节省磁盘空间
  • 恢复速度快

劣势

  • Fork的时候,内存中的数据被克隆了一份,大致2倍的膨胀性需要考虑
  • 虽然Redis在fork时使用了 写时拷贝技术 ,但是如果数据庞大时还是比较消耗性能。
  • 在备份周期在一定间隔时间做一次备份,所以如果Redis意外down掉的话,就会丢失最后一次快照后的所有修改。

Redis持久化之AOF

AOF简介

日志的形式来记录每个写操作(增量保存),将Redis执行过的所有写指令记录下来( 读操作不记录 ), 只许追加文件但不可以改写文件 ,redis启动之初会读取该文件重新构建数据,换言之,redis 重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作

AOF默认不开启,AOF文件的保存路径,同RDB的路径一致,AOF和RDB同时开启,系统默认取AOF的数据(数据不会存在丢失)

AOF启动/修复/恢复

AOF的备份机制和性能虽然和RDB不同, 但是备份和恢复的操作同RDB一样,都是拷贝备份文件,需要恢复时再拷贝到Redis工作目录下,启动系统即加载。

  • 正常恢复
  1. 修改默认的appendonly no,改为yes
  2. 将有数据的aof文件复制一份保存到对应目录(查看目录:config get dir)
  3. 恢复:重启redis然后重新加载
  • 异常恢复
  1. 修改默认的appendonly no,改为yes
  2. 如遇到 AOF文件损坏 ,通过/usr/local/bin/redis-check-aof –fixappendonly.aof进行恢复
  3. 备份被写坏的AOF文件
  4. 恢复:重启redis,然后重新加载

优势

  • 备份机制更稳健,丢失数据概率更低。
  • 可读的日志文本,通过操作AOF稳健,可以处理误操作

劣势

  • 比起RDB占用更多的磁盘空间。
  • 恢复备份速度要慢。
  • 每次读写都同步的话,有一定的性能压力。
  • 存在个别Bug,造成恢复不能。

你可能感兴趣的:(redis,数据库,缓存)