Redis 笔记与总结6 Redis 高级应用之 事务处理、持久化操作、pub_sub、虚拟内存
3.事务处理
redis 对事务的支持目前还比较简单。 redis 只能保证一个 client 发起的事务中的命令可以连续的执行,而中间不会插入其他 client 的命令。 由于 redis 是单线
程来处理所有 client 的请求的所以做到这点是很容易的。一般情况下redis 在接受到一个 client 发来的命令后会立即处理并 返回处理结果,但是当一个client 在
一个连接中发出 multi 命令时,这个连接会进入一个事务上下文,该连接后续的命令并不是立即执行,而是先放到一个队列中。当从此连接受到 exec 命令后
,redis 会顺序的执行队列中的所有命令。并将所有命令的运行结果打包到一起返回给 client.然后此连接就 结束事务上下文。
【例】
127.0.0.1:> get name
"emperor"
127.0.0.1:6379> get age
(nil)
127.0.0.1:> multi
OK #打开事务上下文 127.0.0.1:> set name dee
QUEUED #不立即执行,把命令放入队列 127.0.0.1:> set age
QUEUED 127.0.0.1:> set name king
QUEUED 127.0.0.1:> exec
) OK
) OK
) OK #按队列中命令的顺序开始执行并执行成功 127.0.0.1:> get name
"king" 127.0.0.1:> get age
""
取消一个事务
discard 命令用于取消事务时队列里面的所有命令。
【例】
127.0.0.1:> get name
"king" 127.0.0.1:> multi
OK 127.0.0.1:> set name emperor
QUEUED 127.0.0.1:> set name dee
QUEUED 127.0.0.1:> discard
OK 127.0.0.1:> get name
"king"
这次 2 个 set name 命令都没有被执行,discard 命令其实就是清空事务的命令队列并退出事务上下文,也就是常说的事务回滚。
Redis 事务的不成熟
在关系型数据库例如 MySQL 中,事务中只要有一条语句执行失败则整个事务都将回滚,而 Redis 的事务则是当事务队列中有执行失败的命令时,执行成功的命令依然会执行成功,整个事务不会回滚。
例如 incr name,name 的值是一个字符串类型的值,不能使用增加命令:
127.0.0.1:> incr name
(error) ERR value is not an integer or out of range
在事务中:
127.0.0.1:> get name
"king" 127.0.0.1:> get age
"" 127.0.0.1:> multi
OK 127.0.0.1:> incr age
QUEUED 127.0.0.1:> incr name
QUEUED 127.0.0.1:> exec
) (integer)
) (error) ERR value is not an integer or out of range 127.0.0.1:> get age
"" 127.0.0.1:> get name
"king"
当 incr name 执行失败后,incr age 依然可以执行成功。
乐观锁(和版本控制器类似)
大多数是基于数据版本( version)的记录机制实现的。何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据
库表添加一个“ version ” 字段来实现读取出数据时,将此版本号一同读出,之后更新时,对此版本号加 1。此时,将提交数据的版本号与数据库表对应记录的
当前版本号进行比对,如果提交的数据版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据。
【Redis 乐观锁实例】
假设有一个 age 的 key,我们开 2 个 session 来对 age 进行赋值操作:
第 1 步 session 1
127.0.0.1:> get age
"" 127.0.0.1:> watch age
OK 127.0.0.1:> multi
OK
第 2 步 session 2
127.0.0.1:> set age
OK
127.0.0.1:> get age
""
第 3 步 session 1
127.0.0.1:> set age
QUEUED 127.0.0.1:> exec
(nil) 127.0.0.1:> get age
""
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 # 秒内超过 个 key 被修改,则发起快照保存
快照路径:/usr/local/redis/bin/dump.rdb
【操作】
a. 打开配置文件:
[root@localhost 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.打开配置文件:
[root@localhost bin]# vim /usr/local/redis/etc/redis.conf
b. 搜索 aof
c.默认 appendonly 是 no,改成 yes;
同步方式,默认的配置:
d. 保存退出;
e. 结束 redis 服务;
[root@localhost bin]# pkill redis-server
f. 开启 redis 服务,进入客户端;
[root@localhost bin]# /usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf
[root@localhost bin]# redis-cli -a phpdee
g. 测试:
127.0.0.1:> set name dee
OK 127.0.0.1:> exit [root@localhost bin]# ll
总用量
-rw-r--r--. root root 6月 : appendonly.aof
-rw-r--r--. root root 3月 : dump.rdb
-rwxrwxr-x. root root 12月 mkreleasehdr.sh
-rwxr-xr-x. root root 3月 : redis-benchmark
-rwxr-xr-x. root root 3月 : redis-check-aof
-rwxr-xr-x. root root 3月 : redis-check-dump
-rwxr-xr-x. root root 3月 : redis-cli
-rwxr-xr-x. root root 3月 : redis-server
浏览该文件:
[root@localhost bin]# cat appendonly.aof
*2
$6
SELECT
$1
0
*3
$3
set
$4
name
$3
dee
[root@localhost 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:> subscribe tv1
Reading messages... (press Ctrl-C to quit)
) "subscribe"
) "tv1"
) (integer)
打开第二个客户端(第 2 个 session),开启 redis 服务并进入 redis 客户端,同时监听 tv1 和 tv2 两个频道:
127.0.0.1:> subscribe tv1 tv2
Reading messages... (press Ctrl-C to quit)
) "subscribe"
) "tv1"
) (integer)
) "subscribe"
) "tv2"
) (integer)
打开第三个客户端,开启 redis 服务并进入 redis 客户端,发布消息:
127.0.0.1:> publish tv1 deephper
(integer)
返回 2 代表有 两个人正在监听 tv1
此时第 1 个 session 和 第 2 个 session 会收到 message:
) "message"
) "tv1"
) "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 #redis 使用的最大内存上限
vm-page-size #每个页面的大小 个字节(4k)
vm-pages #最多使用多少页面
vm-max-threads #用于执行 value 对象换入换出的工作线程数量
代开配置文件:
[root@localhost ~]# 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 服务。
开始使用虚拟内存。
Redis 笔记与总结6 Redis 高级应用之 事务处理、持久化操作、pub_sub、虚拟内存的更多相关文章
- Redis 笔记与总结5 Redis 常用命令之 键值命令 和 服务器命令 && 高级应用之 安全性 和 主从复制
Redis 提供了丰富的命令对数据库和各种数据库类型进行操作,这些命令可以在 Linux 终端使用. 1. 键值相关命令: 2. 服务器相关命令 键值相关命令 ① keys 命令 返回满足给定 pat ...
- Redis笔记(八)Redis的持久化
Redis相比Memcached的很大一个优势是支持数据的持久化, 通常持久化的场景一个是做数据库使用,另一个是Redis在做缓存服务器时,防止缓存失效. Redis的持久化主要有快照Snapshot ...
- Redis笔记(二)Redis的部署和启动
Linux下Redis的部署和启动 下载安装介质 Redis官网地址:http://www.redis.io/目前最新版本是redis-3.0.3. 可以访问 http://download.redi ...
- Redis笔记(一)Redis简介
关于Redis Redis是一款开源的高性能键值对数据库,最初的作者是意大利的Salvatore Sanfilippo,他的github是 antirez ,Redis的源码同样托管在Git上:htt ...
- Redis笔记(六)Redis的消息通知
Redis的消息通知可以使用List类型的LPUSH和RPOP(左进右出),当然更方便的是直接使用Redis的Pub/Sub(发布/订阅)模式. >>使用List实现队列 使用列表类型的L ...
- Redis笔记(五)Redis的事务
>>关系型数据库的事务 事务是应用程序中一系列严密的操作,所有操作必须成功完成,否则在每个操作中所作的所有更改都会被撤消. Atomic(原子性): 一个事务(transaction)中的 ...
- Redis笔记(三)Redis的数据类型
前面说过,Redis的一大特性是支持丰富的数据类型, 这为更多的应用场景提供了可能. Redis有五种数据类型,包括string,list,set,sorted set和hash,注意,Redis的数 ...
- 分布式缓存技术redis学习(三)——redis高级应用(主从、事务与锁、持久化)
上文<详细讲解redis数据结构(内存模型)以及常用命令>介绍了redis的数据类型以及常用命令,本文我们来学习下redis的一些高级特性.目录如下: 安全性设置 设置客户端操作秘密 客户 ...
- 【redis】06Redis的高级应用之事务处理、持久化操作、pub_sub、虚拟内存
上节课详细讲解了redis数据库的常用命令,以及redis数据库高级应用当中的, 安全性,跟咱们的主从复制, 这节课呢,咱们继续来讲咱们的高级应用, 首先来看一下咱们的事务处理, 事务处理 我前面说过 ...
随机推荐
- mysql_3
日期查询: mysql> select * from member where birthday > '1962-01-01';
- Material Design综合实例
背景知识 drawlayout的使用 recycleView的使用 CardView的使用 一些开源动画库的使用 ImageView的scaleType属性与adjustViewBounds属性 ,参 ...
- ***linux下用cron定时执行任务的方法
名称 : crontab 使用权限 : 所有使用者 使用方式 : crontab file [-u user]-用指定的文件替代目前的crontab. crontab-[-u user]-用标准输入 ...
- [原]C# Winform 文件编码批量转换工具
在发布产品程序包时,往往需要对程序文件进行编码检查,写了一个可以批量修改文件编码格式的辅助工具,希望对有同样需求的童鞋有帮助. 1.程序界面: 2.核心代码: /// <summary> ...
- 免费电子书:使用VS Online敏捷管理开源项目
今天推荐的是一本由微软出版社发布的免费电子书,涉及的话题是如何在Visual Studio Online中基于敏捷的思想来管理开源项目. 本书的几位作者(自称ALM领域的游侠),给大家分享了在一个敏捷 ...
- androidSDK也要配置环境变量(转)
android的开发人员来说,首先要做的就是环境变量的配置.java是需要配置环境变量的.当然,安卓的环境变量需要我们配置adb的使用,将开发平台的两个工具包配置到环境变量里. 工具/原料 andro ...
- Eddy's digital Roots
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission( ...
- 【Linux程序设计】之Linux库函数的使用,多文件程序开发,静态与共享函数
这个系列的博客贴的都是我大二的时候学习Linux系统高级编程时的一些实验程序,都挺简单的.贴出来纯粹是聊胜于无. 实验题目:Linux基础程序设计综合实验 实验目的:熟悉并掌握Linux库函数的使用, ...
- SZU-A22
Problem(A22):Party Judge InfoMemory Limit: 32768KBCase Time Limit: 10000MSTime Limit: 10000MSJudger: ...
- IE6/IE7下绝对定位position:absolute和margin的冲突问题解决
首先我们来看一个代码: 复制代码代码如下:<div id=”layer1″ style=”margin:20px; border:1px solid #F88; width:400px; “&g ...