NoSql之Redis

NoSQL

NoSQLNot Only SQL),不仅仅是SQL,泛指非关系型的数据库,随着互联网web2.0网站的兴起,传统的关系型数据库在应付web2.0网站,特别是超大规模和高并发地SNS类型的web2.0纯动态网站已经显得力不从心,暴露了很多难以克服的问题,而非关系型的数据库则由其本身的特点得到了非常迅速的发展。NoSQL数据库的产生就是为了解决大规模数据集合多重数据种类带来的挑战,尤其是大数据应用难题,包括超大规模数据的存储。

这些类型的数据存储不需要固定的模式,无需多余操作就可以横向扩展。

ACID

关系型数据库遵循ACID规则
事务在英文中是transaction,和现实世界中的交易很类似,它有如下四个特性:

1、A (Atomicity) 原子性
原子性很容易理解,也就是说事务里的所有操作要么全部做完,要么都不做,事务成功的条件是事务里的所有操作都成功,只要有一个操作失败,整个事务就失败,需要回滚。

2、C (Consistency) 一致性
一致性也比较容易理解,也就是说数据库要一直处于一致的状态,事务的运行不会改变数据库原本的一致性约束。

3、I (Isolation) 独立性
所谓的独立性是指并发的事务之间不会互相影响,如果一个事务要访问的数据正在被另外一个事务修改,只要另外一个事务未提交,它所访问的数据就不受未提交事务的影响。

4、D (Durability) 持久性
持久性是指一旦事务提交后,它所做的修改将会永久的保存在数据库上,即使出现宕机也不会丢失。

CAP

在分布式数据库中的CAP原理:

1、C (Consistency) 强一致性

2、A (Availability) 可用性

3、P (Partition tolerance) 分区容错性

CAP理论的核心是:一个分布式系统不可能同时很好的满足一致性,可用性和分区容错性这三个需求,最多只能同时较好的满足两个

因此,根据 CAP 原理将 NoSQL 数据库分成了满足 CA 原则、满足 CP 原则和满足 AP 原则三 大类:

CA - 单点集群,满足一致性,可用性的系统,通常在可扩展性上不太强大。

CP - 满足一致性,分区容忍必的系统,通常性能不是特别高。

AP - 满足可用性,分区容忍性的系统,通常可能对一致性要求低一些。

redis-01

分布式和集群的简介:

分布式:不同的多台服务器上面部署不同的服务模块(工程),他们之间通过Rpc/Rmi之间通信和调用,对外提供服务和组内协作。

集群:不同的多台服务器上面部署相同的服务模块,通过分布式调度软件进行统一的调度,对外提供服务和访问。

Redis

redis采用单进程模型来处理客户端的请求、对读写等事件的响应。

  1. 默认16个数据库,类似数组下表从零开始,初始默认使用零号库
  1. 默认端口6379

  2. 索引都是从零开始

  3. 常见命令文档Redis命令参考手册完整版

  4. 客户端访问redis-cli -h host -p port -a password

  5. 查询使用文档help @stringhelp @generic

命令 描述
SELECT 切换数据库
Dbsize 查看当前数据库的key的数量
Flushdb 清空当前库
Flushall 通杀全部库

五大数据类型

String

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

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

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

Hash

Hash(哈希) 是一个键值对集合,以string类型的fieldvalue的映射表,hash特别适合用于存储对象。类似Java里面的Map<String,Object>

List

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

Set

Set(集合)是string类型的无序集合。它是通过HashTable实现实现的。

zset

zset(sorted set:有序集合)和set 一样也是string类型元素的集合,且不允许重复的成员。
不同的是每个元素都会关联一个double类型的分数。
redis正是通过分数来为集合中的成员进行从小到大的排序。zset的成员是唯一的,但分数(score)却可以重复。

常用命令

Redis 键(Key)

redis-02

Redis 字符串(String)

redis-03

案例:

getrange:获取指定区间范围内的值,类似between......and的关系,从零到负一表示全部

redis-04

setrange设置指定区间范围内的值,格式是setrange key值 具体值

redis-05

setex:设置带过期时间的keyvalue,原子操作结合,动态设置。

redis-06

setnx:只有在 key 不存在时设置 key 的值。

redis-07

mset:同时设置一个或多个 key-value 对。

redis-08

Redis 列表(List)

redis-09

redis-44

案例:

lpop/rpop:从列表左端/右端移除第一个元素并返回

redis-45

lindex:通过索引获取列表中的元素 lindex key index

redis-46

lrem:从left往right删除2个值等于v1的元素,返回的值为实际删除的数量,LREM list3 0 value,表示删除全部给定的值。零个就是全部值

redis-47

ltrim:截取指定索引区间的元素,格式是ltrim list的key 起始索引 结束索引

redis-48

rpoplpush:移除列表的最后一个元素,并将该元素添加到另一个列表并返回

redis-49

linsert:在list某个已有值的前/后再添加具体值

redis-50

性能总结

它是一个字符串链表,left、right都可以插入添加;如果键不存在,创建新的链表;如果键已存在,新增内容;
如果值全移除,对应的键也就消失了。链表的操作无论是头和尾效率都极高,但假如是对中间元素进行操作,效率就很惨淡了。

Redis 集合(Set)

redis-10

案例

scard:获取集合里面的元素个数

redis-51

serm key value :删除集合中元素

redis-52

srandmember:从set集合里面随机取出2个,如果超过最大数量就全部取出,如果写的值是负数,比如-3 ,表示需要取出3个,但是可能会有重复值。

redis-53

spop key:随机出栈

redis-54

sdiff:在第一个set里而不在后面任何一个set里的项

redis-55

sinter:取交集

redis-56

sunion:取并集

redis-57

Redis 哈希(Hash)

redis-11

Hash十分常用的命令有hset/hget/hmset/hmget/hgetall/hdel/hkeys/hvals

Redis 有序集合(Zset)

set基础上,加一个score值。之前setk1 v1 v2 v3,现在zsetk1 score1 v1 score2 v2

redis-12

zadd/zrange

redis-58

zrangebyscore:zrangebyscore key 开始sorce 结束sorce ,withscores表示携带分数,(表示不包含,limit 用户限制返回数量 limit 开始下标 数量

redis-59

zrem:删除元素,格式是zrem zset的key 项的值,项的值可以是多个

redis-60

zcard :获取集合中元素个数

redis-61

zcount :获取分数区间内元素个数,zcount key 开始分数区间 结束分数区间

redis-62

zrank: 获取value在zset中的下标位置

redis-63

zscore:按照值获得对应的分数

redis-64

zrevrank key values:正序、逆序获得下标索引值

redis-65

zrevrange:按照分数反序输出

redis-66

zrevrangebyscore:zrevrangebyscore key 结束score 开始score

redis-67

配置文件

redis的配置文件在redis的安装目录下,在linux环境下,配置文件命名是redis.conf,在windows系统下是redis.window.conf

Units单位

1
2
3
4
5
6
7
8
9
10
11
12
13
#`redis`在配置文件的开头定义了一些基本的度量单位,并且不区分大小写。
# Redis configuration file example
# Note on units: when memory size is needed, it is possible to specify
# it in the usual form of 1k 5GB 4M and so forth:
#
# 1k => 1000 bytes
# 1kb => 1024 bytes
# 1m => 1000000 bytes
# 1mb => 1024*1024 bytes
# 1g => 1000000000 bytes
# 1gb => 1024*1024*1024 bytes
#
# units are case insensitive so 1GB 1Gb 1gB are all the same.

GENERAL通用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#Redis默认不是以守护进程的方式运行,可以通过该配置项修改,使用yes启用守护进程
daemonize no

#当Redis以守护进程方式运行时,Redis默认会把pid写入/var/run/redis.pid文件,可以通过pidfile指定
pidfile /var/run/redis.pid

#指定Redis监听端口,默认端口为6379
port 6379

#绑定redis对外提供的IP地址
bind 127.0.0.1

#设置tcp的backlog,backlog其实是一个连接队列,backlog队列总和=未完成三次握手队列 + 已经完成三次握手队列。
#在高并发环境下你需要一个高backlog值来避免慢客户端连接问题。
tcp-backlog 511

#当客户端闲置多长时间后关闭连接,如果指定为0,表示关闭该功能
timeout 300

#单位为秒,如果设置为0,则不会进行Keepalive检测,建议设置成60
tcp-keepalive 0

#指定日志记录级别,Redis总共支持四个级别:debug、verbose、notice、warning,生产上一般选择为notice
loglevel notice

#日志记录方式,默认为标准输出
#如果配置Redis为守护进程方式运行,而这里又配置为日志记录方式为标准输出,则日志将会发送给/dev/null
logfile redis.log

#是否把日志输出到syslog中
sys-enabled no

#指定syslog里的日志标志
syslog-ident redis

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

#设置当本机为slave服务时,设置master服务的IP地址及端口,在Redis启动时,它会自动从master进行数据同步
slaveof <masterip> <masterport>

SHAPSHOTTING快照

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# Save the DB on disk:
# save <seconds> <changes>
#触发RDB持久化的三种策略
#指定在多长时间内,有多少次更新操作,就将数据同步到数据文件,可以多个条件配合
#当900秒内出现一次key的变化
save 900 1
#当300秒内出现10次key的变化
save 300 10
#当60秒内出现10000次key的变化
save 60 10000
#如果想禁用RDB持久化的策略,只要不设置任何save指令,或者给save传入一个空字符串参数也可以
#save ""

#如果配置成no,表示你不在乎数据不一致或者有其他的手段发现和控制
stop-writes-on-bgsave-error yes

#对于存储到磁盘中的快照,可以设置是否进行压缩存储。如果是的话,redis会采用LZF算法进行压缩。
#如果你不想消耗CPU来进行压缩的话,可以设置为关闭此功能
rdbcompression yes

#在存储快照后,还可以让redis使用CRC64算法来进行数据校验,但是这样做会增加大约10%的性能消耗
#如果希望获取到最大的性能提升,可以关闭此功能
rdbchecksum yes

#指定本地数据库文件名,默认值为dump.rdb
dbfilename dump.rdb

#指定本地数据库存放目录
dir ./

SECURITY安全

1
2
3
4
5
#当master服务设置了密码保护时,slave服务连接master的密码
masterauth <master-password>

#设置Redis连接密码,如果配置了连接密码,客户端在连接Redis时需要通过AUTH <password>命令提供密码,默认关闭
requirepass foobared

LIMITS限制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#设置同一时间最大客户端连接数,默认无限制,Redis可以同时打开的客户端连接数为Redis进程可以打开的最大文件描述符数
#如果设置 maxclients 0,表示不作限制。当客户端连接数到达限制时,Redis会关闭新的连接并向客户端返回max number of clients reached错误信息
maxclients 128

#指定Redis最大内存限制,Redis在启动时会把数据加载到内存中,达到最大内存后,移除规则可以通过maxmemory-policy来指定。
#当此方法处理后,仍然到达最大内存设置,将无法再进行写入操作,但仍然可以进行读取操作。Redis新的vm机制,会把Key存放内存,Value会存放在swap区
maxmemory <bytes>

#八种移除数据的策略:
#volatile-lru:使用LRU算法移除key,只对设置了过期时间的键
#allkeys-lru:使用LRU算法移除key

#volatile-lfu:从已设置过期时间的数据集挑选使用频率最低的数据淘汰。
#allkeys-lfu:从数据集中挑选使用频率最低的数据淘汰。

#volatile-random:在过期集合中移除随机的key,只对设置了过期时间的键
#allkeys-random:移除随机的key

#volatile-ttl:移除那些TTL值最小的key,即那些最近要过期的key
#noeviction:不进行移除。针对写操作,只是返回错误信息
Maxmemory-policy noeviction

APPEND ONLY MODE追加

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#指定是否在每次更新操作后进行日志记录,Redis在默认情况下是异步的把数据写入磁盘,如果不开启,可能会在断电时导致一段时间内的数据丢失。
#因为redis本身同步数据文件是按上面save条件来同步的,所以有的数据会在一段时间内只存在于内存中。默认为no
appendonly no

#指定更新日志文件名,默认为appendonly.aof
appendfilename appendonly.aof

#指定更新日志条件,共有3个可选值:
#no:表示等操作系统进行数据缓存同步到磁盘(快)
#always:表示每次更新操作后手动调用fsync()将数据写到磁盘(性能差,完整性好)
#everysec:表示每秒同步一次(折衷,默认值)
appendfsync everysec

#重写时是否可以运用Appendfsync,用默认no即可,保证数据安全性。
no-appendfsync-on-rewrite no

#当文件大小是上次重写后大小的一倍且文件大于64M时触发重写
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

其他配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#指定是否启用虚拟内存机制,默认值为no,简单的介绍一下,VM机制将数据分页存放,由Redis将访问量较少的页即冷数据swap到磁盘上,访问多的页面由磁盘自动换出到内存中
vm-enabled no

#虚拟内存文件路径,默认值为/tmp/redis.swap,不可多个Redis实例共享
vm-swap-file /tmp/redis.swap

#将所有大于vm-max-memory的数据存入虚拟内存,无论vm-max-memory设置多小,所有索引数据都是内存存储的(Redis的索引数据 就是keys)
#当vm-max-memory设置为0的时候,其实是所有value都存在于磁盘。默认值为0
vm-max-memory 0

#Redis swap文件分成了很多的page,一个对象可以保存在多个page上面,但一个page上不能被多个对象共享,vm-page-size是要根据存储的数据大小来设定的
#建议如果存储很多小对象,page大小最好设置为32或者64bytes;如果存储很大大对象,则可以使用更大的page,如果不 确定,就使用默认值
vm-page-size 32

#设置swap文件中的page数量,由于页表(一种表示页面空闲或使用的bitmap)是在放在内存中的,,在磁盘上每8个pages将消耗1byte的内存。
vm-pages 134217728

#设置访问swap文件的线程数,最好不要超过机器的核数,如果设置为0,那么所有对swap文件的操作都是串行的,可能会造成比较长时间的延迟。默认值为4
vm-max-threads 4

#设置在向客户端应答时,是否把较小的包合并为一个包发送,默认为开启
glueoutputbuf yes

#指定在超过一定的数量或者最大的元素超过某一临界值时,采用一种特殊的哈希算法
hash-max-zipmap-entries 64
hash-max-zipmap-value 512

#指定是否激活重置哈希,默认为开启
activerehashing yes

#3指定包含其它的配置文件,可以在同一主机上多个Redis实例之间使用同一份配置文件,而同时各个实例又拥有自己的特定配置文件
include /path/to/local.conf

Redis持久化

Redis支持两种数据的持久化方式,分别是RDBAOF,并且支持两种方式共存。

RDB(Redis DataBase)

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

Redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。

整个过程中,主进程是不进行任何IO操作的,这就确保了极高的性能,如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。

RDB的缺点是最后一次持久化后的数据可能丢失

Fork的作用是复制一个与当前进程一样的进程。新进程的所有数据(变量、环境变量、程序计数器等)数值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程。

保存

RDB持久化默认保存的是dump.rdb文件,路径于Redis的安装目录一致,通过savebgsave命令配置触发规则。

1
2
3
4
5
6
7
#redis.conf配置文件的三种策略,关闭则配置 save ""
#当900秒内出现一次key的变化
save 900 1
#当300秒内出现10次key的变化
save 300 10
#当60秒内出现10000次key的变化
save 60 10000

使用save命令时只管保存,其他命令均阻塞,使用bgsave时,Redis会在后台异步进行快照操作,快照同时还可以响应客户端请求。可以通过lastsave命令获取最后一次成功执行快照的时间。

执行flushall命令,会马上产生dump.rdb文件,但里面是空的,无意义。

恢复

可以通过定时备份dump.rdb文件到其他目录,当redis故障时,将备份文件 dump.rdb 移动到 Redis 安装目录并启动服务即可

优势

适合大规模的数据恢复,对数据完整性和一致性要求不高的数据。

劣势

RDB是在一定间隔时间做一次备份,所以如果redis意外down掉的话,就会丢失最后一次快照后的所有修改,而且Fork子进程备份时,内存中的数据被克隆了一份,大致2倍的膨胀性需要考虑。

可以通过动态配置停止RDB保存规则的方法:redis-cli config set save ""

总结

redis-13

  1. RDB是一个非常紧凑的文件
  1. RDB在保存RDB文件时父进程唯一需要做的就是fork出一个子进程,接下来的工作全部由子进程来做,父进程不需要再做其他IO操作,所以RDB持久化方式可以最大化redis的性能

  2. AOF相比,在恢复大的数据集的时候,RDB方式会更快一些

  3. 数据丢失风险大

  4. RDB需要经常fork子进程来保存数据到硬盘上,当数据集比较大的时候,fork的过程是非常耗时的,可能会导致redis在一些毫秒级别不能响应客户端请求

AOF(Append Only File)

AOF持久化策略是以日志的形式来记录每个写操作,将Redis执行过的所有写指令记录下来(读操作不记录),只许追加文件但不可以改写文件,redis启动之初会读取该文件重新构建数据。

换言之,redis重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。

保存

AOF持久化默认保存的是appendonly.aof文件,路径于Redis的安装目录一致,需要通过配置才能开启AOF持久化

1
2
#redis.conf中的AOF持久化开关
appendonly yes

恢复

appendonly.aof文件无损时,直接将该文件拷贝到redis的安装目录下,重启redis即可完成恢复。

appendonly.aof文件受损时,可以在redis的安装目录下执行redis-check-aof --fix appendonly.aof进行文件修复,然后重启redis进行恢复。

AOF采用文件追加方式,文件会越来越大为避免出现此种情况,新增了重写机制,当AOF文件的大小超过所设定的阈值时,Redis就会启动AOF文件的内容压缩,只保留可以恢复数据的最小指令集。

AOF文件持续增长而过大时,会fork出一条新进程来将文件重写(也是先写临时文件最后再rename),遍历新进程的内存中数据,每条记录有一条的Set语句。重写AOF文件的操作,并没有读取旧的AOF文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的AOF文件,这点和快照有点类似。

Redis会记录上次重写时的AOF大小,默认配置是当AOF文件大小是上次重写后大小的一倍且文件大于64M时触发。

1
2
3
4
#redis.conf配置文件
#可以配置重写的百分比及文件大小
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

优势

数据丢失率降低,最多丢失1秒内的数据。

1
2
3
4
5
#指定更新日志条件,共有3个可选值: 
#no:表示等操作系统进行数据缓存同步到磁盘(快)
#always:同步持久化,每次发生数据变更会被立即记录到磁盘 性能较差但数据完整性比较好
#everysec:异步操作,每秒记录一次,如果一秒内宕机,有数据丢失
appendfsync everysec

劣势

相同数据集的数据而言AOF文件要远大于RDB文件,恢复速度慢于RDBAOF运行效率要慢于RDB,每秒同步策略效率较好,不同步效率和RDB相同。

总结

redis-14

  1. AOF文件是一个只进行追加的日志文件
  1. Redis可以在AOF文件体积变得过大时,自动地在后台对AOF进行重写

  2. AOF文件有序地保存了对数据库执行的所有写入操作,这些写入操作以Redis协议的格式保存,因此AOF文件的内容非常容易被人读懂,对文件进行分析也很轻松

  3. 对于相同的数据集来说,AOF文件的体积通常要大于RDB文件的体积

  4. 根据所使用的fsync策略,AOF的速度可能会慢于RDB

总结

  1. RDB持久化方式能够在指定的时间间隔能对你的数据进行快照存储

  2. AOF持久化方式记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据,AOF命令以Redis协议追加保存每次写的操作到文件末尾。Redis还能对AOF文件进行后台重写,使得AOF文件的体积不至于过大

  3. 只做缓存:如果你只希望你的数据在服务器运行的时候存在,也可以不使用任何持久化方式

  4. 同时开启两种持久化方式:

    在这种情况下,当Redis重启的时候会优先载入AOF文件来恢复原始的数据,因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整。

    RDB的数据不实时,同时使用两者时服务器重启也只会找AOF文件。那要不要只使用AOF呢?

    建议不要,因为RDB更适合用于备份数据库(AOF在不断变化不好备份),快速重启,留着作为一个万一的手段。

性能建议:

因为RDB文件只用作后备用途,建议只在Slave上持久化RDB文件,而且只要15分钟备份一次就够了,只保留save 900 1这条规则。

如果Enable AOF,好处是在最恶劣情况下也只会丢失不超过两秒数据,启动脚本较简单只加载自己的AOF文件就可以了。

代价一是带来了持续的IO,二是AOF重写的最后将重写过程中产生的新数据写到新文件造成的阻塞几乎是不可避免的。

只要硬盘许可,应该尽量减少AOF重写的频率,AOF重写的基础大小默认值64M太小了,可以设到5G以上。默认超过原大小100%大小时重写可以改到适当的数值。

如果不Enable AOF ,仅靠Master-Slave Replication 实现高可用性也可以。能省掉一大笔IO也减少了重写时带来的系统波动。代价是如果Master/Slave同时倒掉,会丢失十几分钟的数据,启动脚本也要比较两个Master/Slave中的RDB文件,载入较新的那个。

Redis事务

Redis事务是指可以一次执行多个命令,本质是一组命令的集合。一个事务中的所有命令都会序列化,按顺序地串行化执行而不会被其它命令插入,不许加塞

可以用来一个队列中,一次性、顺序性、排他性的执行一系列命令。

常用命令

redis-15

正常执行

redis-16

放弃事务

redis-17

全体连坐

redis-18

不符合Redis协议的语法错误,类似于Java的编译错误一样,会导致整个事务执行失败。

冤头债主

redis-19

符合Redis协议的语法,但是在运行中异常,类似于Java的运行时错误一样,只会导致该条命令执行失败,不会影响及回滚其他命令。

Watch监控

悲观锁

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

乐观锁

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

乐观锁策略:提交版本必须大于记录当前版本才能执行更新

无加塞

redis-20

先监控再开启multi,保证两笔金额变动在同一个事务内。

有加塞

redis-21

监控了key,如果key被修改了,后面一个事务的执行失效。

unwatch

redis-22

小结

  1. 一旦执行了exec之前加的监控锁都会被取消掉了
  2. Watch指令,类似乐观锁,事务提交时,如果Key的值已被别的客户端改变,比如某个list已被别的客户端push/pop过了,整个事务队列都不会被执行
  3. 通过watch命令在事务执行之前监控了多个Keys,倘若在watch之后有任何Key的值发生了变化,exec命令执行的事务都将被放弃,同时返回Nullmulti-bulk应答以通知调用者事务执行失败
  4. 如果watch监控后Key值发生了变化,只能通过重新查询新值再重新开启事务进行操作

总结

开启事务后的三个阶段:

  1. 开启:以MULTI开始一个事务
  1. 入队:将多个命令入队到事务中,接到这些命令并不会立即执行,而是放到等待执行的事务队列里面

  2. 执行:由EXEC命令触发事务

开启事务后的三个特性:

  1. 单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
  1. 没有隔离级别的概念:队列中的命令没有提交之前都不会实际的被执行,因为事务提交前任何指令都不会被实际执行,也就不存在”事务内的查询要看到事务里的更新,在事务外查询不能看到”这个让人万分头痛的问题

  2. 不保证原子性:redis同一个事务中如果有一条命令执行失败,其后的命令仍然会被执行,没有回滚

Redis发布订阅

redis-23

必须要先订阅后发布才能收到消息

redis-24

执行PUBLISH c2 hello-redis即可对c2频道发布消息,支持订阅多个的通配符PSUBSCRIBE new*,发送消息PUBLISH new1 redis2015

最后更新: 2021年01月20日 23:43

原始链接: https://midkuro.gitee.io/2020/05/23/redis-nosql/

× 请我吃糖~
打赏二维码