Redis事务以及锁的简单介绍

Redis

“ 耐心之树,结黄金之果 ”


本篇只是简单介绍了Redis的概念,以及它的事务和锁,在事务这里,很多文章说Redis并不支持事务的原子性,但在官方文档表达的Redis是支持原子性的(命令要么全执行,要么全不执行)。但不保证完全执行成功。还要注意Redis不存在事务隔离级别。
可以根据目录跳转到想了解的地方~

官网:https://redis.io

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性能测试

image-20221011214109149

可参考:https://www.runoob.com/redis/redis-benchmarks.html

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)

image-20221012100559215

放弃事务(DISCARD)

事务队列中的命令都不会被执行


事务原子性问题

编译型异常,指令错误,事务中所有命令都不会被执行

image-20221012112835331

运行型异常,语法错误,事务队列中出现语法错误,错误命令抛异常,其他命令可正常执行

image-20221012102850968

总结:

  • Redis官方文档给的理解是,Redis的事务是原子性的:所有的命令,要么全部执行,要么全部不执行。而不是完全成功!

4、锁

悲观锁

认为什么时候都会出现问题

乐观锁

认为什么时候都不会出问题,不会上锁,更新数据时会判断是否被修改(获取version,比较version)

redis监视测试 WATCH与UNWATCH实现乐观锁

被 WATCH 的键会被监视,并会发觉这些键是否被改动过了。 如果有至少一个被监视的键在 EXEC 执行之前被修改了, 那么整个事务都会被取消

  • watch如何监控?

img

正常操作下:

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

此时再执行事务发现:事务执行失败!!!

image-20221012203152849

  • 解锁用UNWATCH

1、如果发现事务执行失败,先解锁

2、再次监视,获取最新的值

3、比对监视值是否发生变化,如果没变化,可以执行成功,如果变化了,执行失败!修改失败,再次获取新值监视即可。

image-20221012204205999

我可能写的有点乱,尽量精简记录 ~

参考来源

https://redis.io/docs/about/

https://www.pdai.tech

posted @ 2022-10-12 20:54  来日可追  阅读(87)  评论(0编辑  收藏  举报