Redis事务以及锁的简单介绍
Redis
“ 耐心之树,结黄金之果 ”
本篇只是简单介绍了Redis的概念,以及它的事务和锁,在事务这里,很多文章说Redis并不支持事务的原子性,但在官方文档表达的Redis是支持原子性的(命令要么全执行,要么全不执行)。但不保证完全执行成功。还要注意Redis不存在事务隔离级别。
可以根据目录跳转到想了解的地方~
Redis是一个开源的基于内存的非关系型数据库,用作数据库、缓存、消息代理和流引擎。Redis提供数据结构,如字符串、散列、列表、集、带范围查询的排序集、位图、超对数、地理空间索引和流。Redis有内置的复制、Lua脚本、LRU逐出、事务和不同级别的磁盘持久性,并通过Redis Sentinel和Redis Cluster自动分区提供高可用性。
1、NoSQL
为什么要用?
用户个人信息、社交网络、地理位置、用户产生的数据、用户日志等爆发式增长,NoSQL可以很好地处理这些情况。而且这些数据类型的存储不需要固定的格式。
NoSQL ?
不仅仅是SQL,泛指非关系型数据库,一些大规模、高并发的社区暴露出很多难以克服的问题,NoSQL发展十分迅速!
特点
1、方便扩展(数据间没有关系)
2、大数据量高性能
3、数据类型多样,不需要事先设计数据库,随取随用
传统的 RDBMS(关系型数据库):
- 结构化组织 - SQL
- 数据和关系都存在单独的表中 row col
- 操作,数据定义语言
- 严格的一致性
- 基础的事务
Nosql - 不仅仅是数据
- 没有固定的查询语言
- 键值对存储,列存储,文档存储,图形数据库(社交关系)
- 最终一致性
- CAP定理和BASE
- 高性能,高可用,高扩展
1.1 NoSQL的四大分类:
- 键值(Key-Value)存储数据库。使用到一个哈希表,这个表中有一个指针指向特定的数据。Redis,Memcache。 查找快
- 列存储数据库。HBase。
- 文档型数据库。MongoDB,SQLite。
- 图形数据库。Infinite Graph。(放的是关系,比如:朋友圈社交网络,广告推荐)
MongoDB基于分布式文件存储的数据库,C++编写,
主要用于处理大量文档,介于非关系型数据库和关系型数据库之间,是非关系型数据库中功能最丰富,最像关系型数据库的
1.2 NoSQL应用场景:
1、数据模型比较简单
2、数据灵活性更强
3、对数据库性能要求比较高
4、不需要高度的数据一致性
2、Redis
Remote Dictionary Server
-
Redis是一种支持key-value等多种数据结构的存储系统。可用于缓存,事件发布或订阅,高速队列等场景。支持网络,提供字符串,哈希,列表,队列,集合结构直接存取,基于内存,可持久化
(内存存储、持久化,内存是断电即失的,所以需要持久化(RDB、AOF))。
在服务器上安装Redis看这:https://www.cnblogs.com/fulfill/p/16776854.html
2.1 redis-benchmark性能测试
2.2 基础
redis 默认有16个数据库,默认使用的是第0个数据库
可以通过select n
来选择使用的数据库 比如:select 2 (选择使用第2个数据库);DBSIZE(可查看DB大小)
3、事务
redis事务本质:一组命令的集合!一个事务中所有命令都会被序列化,事务在执行过程中,会按照顺序执行,一次性、顺序性、排他性
-
redis 单条命令是原子性的,但是事务不保证原子性
-
redis事务是严格遵守隔离性的,原因是redis是单进程单线程模式(v6.0之前),可以保证命令执行过程中不会被其他客户端命令打断。但不存在隔离级别!
-
redis事务可以保证命令失败的情况下得以回滚,数据能恢复到没有执行之前的样子,是保证一致性的,除非redis进程意外终结。
-
redis事务是不保证持久性的,这是因为redis持久化策略中不管是RDB还是AOF都是异步执行的,不保证持久性是出于对性能的考虑。
所有命令在事务中,并没有直接被执行,只有发起执行命令时才会被执行!EXEC
开启事务 ( MULTI)
命令入队 (一些指令)
执行事务 ( EXEC)
放弃事务(DISCARD)
事务队列中的命令都不会被执行
事务原子性问题
编译型异常,指令错误,事务中所有命令都不会被执行
运行型异常,语法错误,事务队列中出现语法错误,错误命令抛异常,其他命令可正常执行
总结:
- Redis官方文档给的理解是,Redis的事务是原子性的:所有的命令,要么全部执行,要么全部不执行。而不是完全成功!
4、锁
悲观锁
认为什么时候都会出现问题
乐观锁
认为什么时候都不会出问题,不会上锁,更新数据时会判断是否被修改(获取version,比较version)
redis监视测试 WATCH与UNWATCH实现乐观锁
被 WATCH 的键会被监视,并会发觉这些键是否被改动过了。 如果有至少一个被监视的键在 EXEC 执行之前被修改了, 那么整个事务都会被取消
- watch如何监控?
正常操作下:
127.0.0.1:6379> set money 100
OK
127.0.0.1:6379> set out 0
OK
127.0.0.1:6379> watch money # 监视
OK
127.0.0.1:6379> multi # 开启事务
OK
127.0.0.1:6379> DECRBY money 20
QUEUED
127.0.0.1:6379> INCRBY out 20
QUEUED
127.0.0.1:6379> EXEC # 执行事务,一旦事务执行成功,监控会自动取消
1) (integer) 80
2) (integer) 20 # 数据保持一致
那要是另外的一个线程又来了如何?
# 线程一:
127.0.0.1:6379> watch money # 监控
OK
127.0.0.1:6379> MULTI # 开启事务
OK
127.0.0.1:6379> decrby money 20
QUEUED
127.0.0.1:6379> incrby out 20
QUEUED
# 注意此时事务还没执行
同时线程二也来修改了!!!
# 线程二:
127.0.0.1:6379> set money 2000 # 被修改了!
OK
此时再执行事务发现:事务执行失败!!!
- 解锁用UNWATCH
1、如果发现事务执行失败,先解锁
2、再次监视,获取最新的值
3、比对监视值是否发生变化,如果没变化,可以执行成功,如果变化了,执行失败!修改失败,再次获取新值监视即可。
我可能写的有点乱,尽量精简记录 ~