Redis 笔记与总结6 Redis 高级应用之 事务处理、持久化操作、pub_sub、虚拟内存

3.事务处理

redis 对事务的支持目前还比较简单。 redis 只能保证一个 client 发起的事务中的命令可以连续的执行,而中间不会插入其他 client 的命令。 由于 redis 是单线

程来处理所有 client 的请求的所以做到这点是很容易的。一般情况下redis 在接受到一个 client 发来的命令后会立即处理并 返回处理结果,但是当一个client 在

一个连接中发出 multi 命令时,这个连接会进入一个事务上下文,该连接后续的命令并不是立即执行,而是先放到一个队列中。当从此连接受到 exec 命令后

redis 会顺序的执行队列中的所有命令。并将所有命令的运行结果打包到一起返回给 client.然后此连接就 结束事务上下文。

【例】

127.0.0.1:6379> get name
"emperor" 

127.0.0.1:6379> get age
  (nil)

127.0.0.1:6379> multi
OK    #打开事务上下文

127.0.0.1:6379> set name dee
QUEUED   #不立即执行,把命令放入队列

127.0.0.1:6379> set age 27
QUEUED   

127.0.0.1:6379> set name king
QUEUED

127.0.0.1:6379> exec
1) OK
2) OK
3) OK  #按队列中命令的顺序开始执行并执行成功

127.0.0.1:6379> get name
"king"

127.0.0.1:6379> get age
"27"

取消一个事务

discard 命令用于取消事务时队列里面的所有命令。

【例】

127.0.0.1:6379> get name
"king"

127.0.0.1:6379> multi
OK

127.0.0.1:6379> set name emperor
QUEUED

127.0.0.1:6379> set name dee
QUEUED

127.0.0.1:6379> discard
OK

127.0.0.1:6379> get name
"king"

这次 2 个 set name 命令都没有被执行,discard 命令其实就是清空事务的命令队列并退出事务上下文,也就是常说的事务回滚

Redis 事务的不成熟

在关系型数据库例如 MySQL 中,事务中只要有一条语句执行失败则整个事务都将回滚,而 Redis 的事务则是当事务队列中有执行失败的命令时,执行成功的命令依然会执行成功,整个事务不会回滚。

例如 incr name,name 的值是一个字符串类型的值,不能使用增加命令:

127.0.0.1:6379> incr name
(error) ERR value is not an integer or out of range

在事务中:

127.0.0.1:6379> get name
"king"

127.0.0.1:6379> get age
"27"

127.0.0.1:6379> multi
OK

127.0.0.1:6379> incr age
QUEUED

127.0.0.1:6379> incr name
QUEUED

127.0.0.1:6379> exec
1) (integer) 28
2) (error) ERR value is not an integer or out of range

127.0.0.1:6379> get age
"28"

127.0.0.1:6379> get name
"king"

当 incr name 执行失败后,incr age 依然可以执行成功。

乐观锁(和版本控制器类似)

大多数是基于数据版本( version)的记录机制实现的。何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据

库表添加一个“ version ” 字段来实现读取出数据时,将此版本号一同读出,之后更新时,对此版本号加 1。此时,将提交数据的版本号与数据库表对应记录的

当前版本号进行比对,如果提交的数据版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据。

【Redis 乐观锁实例】

假设有一个 age 的 key,我们开 2 个 session 来对 age 进行赋值操作:

第 1 步 session 1

127.0.0.1:6379> get age
"29" 

127.0.0.1:6379> watch age
OK

127.0.0.1:6379> multi
OK

第 2 步 session 2

127.0.0.1:6379> set age 30
OK
127.0.0.1:6379> get age
"30"

第 3 步 session 1

127.0.0.1:6379> set age 20
QUEUED

127.0.0.1:6379> exec
(nil)

127.0.0.1:6379> get age
"30"

watch 命令会监视给定的 key当 exec 时候如果监视的 key 从调用 watch 后发生过变化,则整个事务会失败。也可以调用 watch 多次监视多个

key。这样就可以对指定的 key 加乐观锁了。注意 watch 的 key 是对整个连接有效的,事务也一样。如果连接断开,监视和事务都会被自动清除。当然了

exec,discard,unwatch 命令都会清除连接中的所有监视

4.持久化机制

redis 是一个支持持久化的内存数据库,也就是说 redis 需要经常将内存中的数据同步到磁盘来保证持久化。 redis 支持两种持久化方式,一种是

Snapshotting(快照)也是默认方式(将数据存入文件),另一种是 Append-only file(缩写 aof)的方式(将操作存入文件)。

①  Snapshotting 方式

快照是默认的持久化方式。这种方式是就是将内存中数据以快照的方式写入到二进制文件中,默认的文件名为 dump.rdb。可以通过配置设置自动做快照持久

化的方式。我们可以配置 redis在 n 秒内如果超过 m 个 key 被修改就自动做快照。

save 60 10000  #60 秒内超过 10000 个 key 被修改,则发起快照保存

快照路径:/usr/local/redis/bin/dump.rdb

【操作】

a. 打开配置文件:

[[email protected] bin]# vim /usr/local/redis/etc/redis.conf 

b. 搜索 save:

默认开启了 3 种方式:

save 900 1

save 300 10

save 60 10000

aof 方式

由于快照方式是在一定间隔时间做一次的,所以如果 redis 意外 down 掉的话,就会丢失最后一次快照后的所有修改。如果应用要求不能丢失任何修改的话,

可以采用 aof 持久化方式。下面介绍 Append-only file:

aof 比快照方式有更好的持久化性,是由于在使用 aof 持久化方式时,redis 会将每一个收到的写命令都通过 write 函数追加到文件中(默认是

appendonly.aof)。当 redis 重启时会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容。当然由于 os 会在内核中缓存 write 做的修改,

所以可能不是立即写到磁盘上。这样 aof 方式的持久化也还是有可能会丢失部分修改。不过我们可以通过配置文件告诉 redis 我们想要通过 fsync 函数强制

os 写入到磁盘的时机。有三种方式如下(默认是:每秒 fsync 一次)

appendonly yes //启用 aof 持久化方式
# appendfsync always //收到写命令就立即写入磁盘,最慢,但是保证完全的持久化
appendfsync everysec //每秒钟写入磁盘一次,在性能和持久化方面做了很好的折中
# appendfsync no //完全依赖 os,性能最好,持久化没保证

【操作】

a.打开配置文件:

[[email protected] bin]# vim /usr/local/redis/etc/redis.conf 

b. 搜索 aof

c.默认 appendonly 是 no,改成 yes;

同步方式,默认的配置:

d. 保存退出;

e. 结束 redis 服务;

[[email protected] bin]# pkill redis-server 

f. 开启 redis 服务,进入客户端;

[[email protected] bin]# /usr/local/redis/bin/redis-server  /usr/local/redis/etc/redis.conf
[[email protected] bin]# redis-cli -a phpdee 

g. 测试:

127.0.0.1:6379> set name dee
OK

127.0.0.1:6379> exit

[[email protected] bin]# ll
总用量 13688
-rw-r--r--. 1 root root      55 6月  28 04:44 appendonly.aof
-rw-r--r--. 1 root root      18 3月  18 08:09 dump.rdb
-rwxrwxr-x. 1 root root     566 12月 16 2014 mkreleasehdr.sh
-rwxr-xr-x. 1 root root 4169079 3月  17 06:40 redis-benchmark
-rwxr-xr-x. 1 root root   16415 3月  17 06:40 redis-check-aof
-rwxr-xr-x. 1 root root   37647 3月  17 06:40 redis-check-dump
-rwxr-xr-x. 1 root root 4249851 3月  17 06:40 redis-cli
-rwxr-xr-x. 1 root root 5519070 3月  17 06:40 redis-server

浏览该文件:

[[email protected] bin]# cat appendonly.aof
*2
$6
SELECT
$1
0
*3
$3
set
$4
name
$3
dee
[[email protected] bin]#

  

5.发布与订阅信息

发布订阅(pub/sub)是一种消息通信模式,主要的目的是解耦消息发布者和消息订阅者之间的耦合,这点和设计模式中的观察者模式比较相似。 pub/sub 不

仅仅解决发布者和订阅者直接代码级别耦合也解决两者在物理部署上的耦合。 redis 作为一个 pub/sub 的 server,在订阅者和发布者之间起到了消息路由

功能。订阅者可以通过 subscribe psubscribe 命令向 redis server 订阅自己感兴趣的消息类型, redis 将消息类型称为通道(channel)。当发布者通

过 publish 命令向 redis server 发送特定类型的消息时。订阅该消息类型的全部 client 都会收到此消息。这里消息的传递是多对多的。一个 client 可以订

阅多个 channel,也可以向多个 channel发送消息。

【例】(打开3个 session :打开3个客户端连接)

在第一个客户端(第 1 个 session)开启 redis 服务并进入 redis 客户端,开始监听 tv1 这个频道:

127.0.0.1:6379> subscribe tv1
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "tv1"
3) (integer) 1

打开第二个客户端(第 2 个 session),开启 redis 服务并进入 redis 客户端,同时监听 tv1 和 tv2 两个频道:

127.0.0.1:6379> subscribe tv1 tv2
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "tv1"
3) (integer) 1
1) "subscribe"
2) "tv2"
3) (integer) 2

打开第三个客户端,开启 redis 服务并进入 redis 客户端,发布消息:

127.0.0.1:6379> publish tv1 deephper
(integer) 2

返回 2 代表有 两个人正在监听 tv1

此时第 1 个 session 和 第 2 个 session 会收到 message:

1) "message"
2) "tv1"
3) "deephper"

此时第 3 个 session 继续发布 tv2:

返回 1 ,代表有 1 个人正在监听 tv2;同时 session 2 弹出信息:

注:可以实现消息系统和 web 聊天系统。

6. 虚拟内存的使用

redis 的虚拟内存与操作系统的虚拟内存不是一码事,但是思路和目的都是相同的。就是暂时把不经常访问的数据从内存交换到磁盘中,从而腾出宝贵的内存

空间用于其他需要访问的数据。尤其是对于 redis 这样的内存数据库,内存总是不够用的。除了可以将数据分割到多个 redis server 外。另外的能够提高数据

库容量的办法就是使用虚拟内存把那些不经常访问的数据交换的磁盘上

【配置】

#vm 相关配置
vm-enabled yes #开启 vm 功能
vm-swap-file /tmp/redis.swap #交换出来的 value 保存的文件路径
vm-max-memory 1000000 #redis 使用的最大内存上限
vm-page-size 32 #每个页面的大小 32 个字节(4k)
vm-pages 134217728 #最多使用多少页面
vm-max-threads 4 #用于执行 value 对象换入换出的工作线程数量

代开配置文件:

[[email protected] ~]# vim /usr/local/redis/etc/redis.conf

搜索 vm(我的 redis 2.8.19 没有在 配置文件中看到 vm 配置);

no 改成 yes;

vm-max-memory 指定为 100000;

保存退出。

重启 redis 服务:

把 really-use-vm yes 添加进配置文件;

保存退出;

重启 redis 服务。

开始使用虚拟内存。

时间: 2024-10-01 03:02:19

Redis 笔记与总结6 Redis 高级应用之 事务处理、持久化操作、pub_sub、虚拟内存的相关文章

Redis 笔记与总结5 Redis 常用命令之 键值命令 和 服务器命令 && 高级应用之 安全性 和 主从复制

Redis 提供了丰富的命令对数据库和各种数据库类型进行操作,这些命令可以在 Linux 终端使用. 1. 键值相关命令: 2. 服务器相关命令 键值相关命令 ① keys 命令 返回满足给定 pattern 的所有 key. [例] 127.0.0.1:6379> keys * 1) "time" 2) "list4" 3) "list1" 4) "email" 5) "age" 6) "

小蚂蚁学习Redis笔记(1)——Redis简介、适用场景、对比

Nosql    =    not only sql    反sql运动,非关系型数据库 Nosql是以key-value形式存储,和传统的关系型数据库形成对比. Nosql有以下几个特点:非关系型的,分布式,开源的,水平可拓展的. 优点: 1. 处理超大量的数据    2. 运行在便宜的PC服务器集群上    3. 击碎了性能瓶颈 Nosql的适用场景: 1. 对数据高并发读写    2. 对海量数据的高效率存储和访问    3. 对数据的高可扩展性和高可用性 ps:扩展性好主要体现在它没有一

小蚂蚁学习Redis笔记(2)——Redis安装和配置

Redis的安装 下载地址    http://redis.io/download 选择一个最新的稳定版本,目前是 redis-3.0.5.tar.gz (选择stable,稳定版本) 解压压缩包    tar -zxvf    redis-3.0.5.tar.gz 进入该目录    cd    redis-3.0.5 编译              make    这里需要注意一下,如果出现报错,记得最后一句有个error 2,使用了命令  make MALLOC=libc 即可. 安装   

小蚂蚁学习Redis笔记(5)——Redis数据类型之list类型

Redis之lists类型以及操作 list是一个链表结构,主要功能是push.pop,获取一个范围的所有值等等.操作中key理解为链表的名字.Redis的list类型其实就是一个每个子元素都是string类型的双向链表.可以通过push.pop操作从链表的头部或者尾部添加删除元素,这样list既可以作为栈,也可以作为队列. 栈和队列的特性    栈:先进后出:队列:先进先出. 1.    lpush    为链表的头部添加字符串元素 格式:    lpush    mylist1    "al

小蚂蚁学习Redis笔记(3)——Redis数据类型之string类型

昨天安装完毕,今天终于可以进入正题了. Redis中string类型的常用命令: string是最简单的类型,一个key对应一个value,string类型是二进制安全的类型,Redis的string可以包含任何数据,比如:图片或者序列化的对象. 1.    set    设置一对键值 格式:set    键    值        例如:set     name    "allen" 含义:添加一个键值对. 值得注意的是,这个命令在设置重复的key时,value是会覆盖的.它的作用是

小蚂蚁学习Redis笔记(4)——Redis数据类型之hashes类型

hashes类型 hash是一个string类型的field和value的映射表.它特别适合用于存储对象.相较于将对象的每个字段存成单个的string类型,将一个对象存储在hash类型中会占用更少的内存,并且可以更方便的存取整个对象. hashes常用命令 1.    hset    设置对象的字段和值 格式:    hset    user:001    name    "allen" 含义:为user:001这个对象,将它的name键设置一个值为allen. 注意:如果同样的对象,

Redis笔记整理(三):进阶操作与高级部分

[TOC] Redis笔记整理(三):进阶操作与高级部分 Redis发布订阅 Redis发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息. Redis客户端可以订阅任意数量的频道. 下图展示了频道channel1,以及订阅这个频道的三个客户端--client1,client2,client5之间的关系. 当有新消息通过PUBLISH命令发送给频道channel1时,这个消息就会被发送给订阅它的三个客户端: 相关操作命令如下: 命令 描述 PSUBS

redis笔记

redis笔记 下载完redis,执行make命令. 然后启动redis就进src文件夹,执行./redis-server就可以了. 再在文件夹下执行 ./redis-cli 就可以执行redis的命令了. pipelining  一次请求发送多个命令,以提高性能.我们在使用redis时都是向它发送命令,每次都是需要和redis建立tcp连接,然后发送命令信息,redis执行命令后,客户端等待着redis的响应.这个我们当然知道,就像访问db,IO开销都是消耗资源的大头,所以redis提供了pi

点滴记录——学习Redis笔记

转载请说明出处:http://blog.csdn.net/cywosp/article/details/39701409 Redis 默认端口6379 Redis适用场景 1. 取最新N个数据的操作 2. 排行榜应用,取TOP N操作 3. 需要精确设定过期时间的应用 4. 计数器应用 5. Uniq操作,获取某段时间所有数据排重值 6. 实时系统,反垃圾系统 7. Pub/Sub构建实时消息系统--消息的发布与订阅 8. 构建队列系统 9. 缓存 Redis数据类型 Strings类型及操作