Redis简述
NoSQL数据库简介
技术发展
Web1.0时代
Web2.0时代
解决CPU及内存压力
解决IO压力
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 键 (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 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。
它的底层实际是个双向链表,对两端的操作性能很高,通过索引下标的操作中间的节点性能会较差。
命令 | 描述 |
---|---|
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<String,Object>
用户ID为查找的key,存储的value用户对象包含姓名,年龄,生日等信息,如果用普通的key/value结构来存储
主要有以下2种存储方式:
每次修改用户的某个属性需要, | |
先反序列化改好后再序列化回去。开销较大。 | 用户ID数据冗余 |
?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来放弃组队。
事务的错误处理
组队中某个命令出现了报告错误,执行时整个的所有队列都会被取消。
如果执行阶段某个命令报出了错误,则只有报错的命令不会被执行,而其他的命令都会执行,不会回滚。
悲观锁
悲观锁(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
优势
- 适合大规模的数据恢复
- 对数据完整性和一致性要求不高更适合使用
- 节省磁盘空间
- 恢复速度快
劣势
- Fork的时候,内存中的数据被克隆了一份,大致2倍的膨胀性需要考虑
- 虽然Redis在fork时使用了 写时拷贝技术 ,但是如果数据庞大时还是比较消耗性能。
- 在备份周期在一定间隔时间做一次备份,所以如果Redis意外down掉的话,就会丢失最后一次快照后的所有修改。
Redis持久化之AOF
AOF简介
以日志的形式来记录每个写操作(增量保存),将Redis执行过的所有写指令记录下来( 读操作不记录 ), 只许追加文件但不可以改写文件 ,redis启动之初会读取该文件重新构建数据,换言之,redis 重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作
AOF默认不开启,AOF文件的保存路径,同RDB的路径一致,AOF和RDB同时开启,系统默认取AOF的数据(数据不会存在丢失)
AOF启动/修复/恢复
AOF的备份机制和性能虽然和RDB不同, 但是备份和恢复的操作同RDB一样,都是拷贝备份文件,需要恢复时再拷贝到Redis工作目录下,启动系统即加载。
- 正常恢复
- 修改默认的appendonly no,改为yes
- 将有数据的aof文件复制一份保存到对应目录(查看目录:config get dir)
- 恢复:重启redis然后重新加载
- 异常恢复
- 修改默认的appendonly no,改为yes
- 如遇到 AOF文件损坏 ,通过/usr/local/bin/redis-check-aof –fixappendonly.aof进行恢复
- 备份被写坏的AOF文件
- 恢复:重启redis,然后重新加载
优势
- 备份机制更稳健,丢失数据概率更低。
- 可读的日志文本,通过操作AOF稳健,可以处理误操作
劣势
- 比起RDB占用更多的磁盘空间。
- 恢复备份速度要慢。
- 每次读写都同步的话,有一定的性能压力。
- 存在个别Bug,造成恢复不能。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!