前面已经学习了redis的基本的命令行操作和数据类型,下面开始redis一些有趣的功能。

订阅和发布机制

  • 定义:发布者相当于电台,订阅者相当于客户端,客户端发到频道的消息,将会被推送到所有订阅此频道的客户端;客户端不需要主动去获取消息,只需要订阅频道,这个频道的内容就会被推送过来;

  • 作用:发布者和订阅者的解耦合可以带来更大的扩展性和更加动态的网络拓扑;

相关命令

# 订阅消息
subscribe 频道1 频道2 # 此时redis客户端会一直处于监听频道的状态,一有消息就处理;
# 取消订阅
unsubcribe 频道1 ... # 如果不写频道名称,则取消所有的订阅; # 推送消息
publish 频道1 消息内容

重点说明

  • 发布订阅机制一般使用在对同一个redis实例来说,实现类似于生产者消费者模式;

  • 在主从集群中,master发布的消息可以推送到slave中,但slave中的消息不能推送到master中;

订阅发布机制的不足:

  1. 如果消息接收方不能及时处理推送的消息,消息会在缓存队列中,会导致缓存占用的空间越来越大,最终导致redis崩溃;

  2. 发布的消息推送存在即时性,但网络一般是不稳定的,对于客户端来说,如果出现了断网的现象,那么接收的消息就会丢失,所以发布订阅模式不能用在对数据完整性要求高的场合;

简单的主从复制配置

  • 定义:一台redis服务器可以作为一个master,在其下面可以有多个slave,每个slave又可以作为一个master,从而可以构建庞大的redis数据库集群;

配置方法

方式一:修改配置文件

# 设置主服务器的配置,绑定固定的ip
sudo vi redis.conf
bind 服务器的ip # 设置从服务器的ip
sudo vi redis.conf
bind 服务器的ip
slaveof 主服务器的ip 主服务器redis端口 # 注意,ip与端口之间使用空格分割 # 分别启动主从redis,主服务器redis负责写,也可以读;从服务器只能读,不能写;

方式二:使用命令行的方式动态设置

# 从服务器连接主服务器
slaveof host port
# 从服务器断开主服务器
slaveof no one

重要说明

  • 从服务器与主服务器进行初始连接时,从服务器会丢弃所有的旧数据,然后载入主服务器的数据;

  • redis不支持主主复制,也就是说不可以两个redis相互设置对方为主服务器,虽然不会报错,但性能方面,以及对客户端的请求都可能出现问题;

redis复制的启动过程

  • 当主服务器收到从服务器发送的复制请求的时候,主服务器执行的动作有:

等待从服务器的命令进入-->执行bgsave,创建快照文件;使用缓存区记录bgsave命令执行后所有的写命令-->快照文件创建完毕后,向服务器发送快照文件-->发送快照文件完毕后向从服务器发送缓存区的写命令-->完毕后每收到一个写命令就向从服务器发送

  • 从服务器相应的动作有:

连接主服务器,发送sync命令-->等待响应-->丢弃所有的旧数据,载入主服务器的快照文件-->完成快照文件的解释,开始接受命令请求-->执行从主服务器发送的所有的写命令;

注意:redis支持主从链,即从服务器还可以有从服务器,但是从服务器A复制从服务器B的过程和从服务器B复制主服务器是有区别的;从服务器B向从服务器A发送完毕快照文件后,会先断开与从服务器A的连接,从服务器A需要重新连接并且请求同步;

redis的事务

  • redis有像关系型数据库一样的事务机制来保证多条命令作为原子操作;事务中的命令要么全执行,要么全不执行;

  • 事务的完整过程:开始事务-->命令进入缓存-->执行事务;

事务的基本使用

# 开启一个事务
multi # 提交命令后,redis会将后面的操作保存起来
# 提交事务
exec # 提交命令后,redis会执行前面保存的所有的命令 # 取消事务
discard # 如果书写命令队列的过程中需要取消事务时使用
  • redis事务中在写命令队列的时候,如果中间发生了语法错误,并且redis报了错,那么这个事务所有的命令都会取消执行;
> lpush list a b c
(integer) 3
> multi
OK
> lpush list d
QUEUED
> lpuxh list f
(error) ERR unknown command 'lpuxh'
> lrange list 0 10
QUEUED
> exec
(error) EXECABORT Transaction discarded because of previous errors.
> lrange list 0 10
1) "c"
2) "b"
3) "a" # 所有的命令都没有执行
  • 但有一些错误redis在执行之前并不能感知,这时redis会执行所有的的命令,客户端必须自己处理错误;
> lpush li blue red green
(integer) 3
> multi
OK
> get li
QUEUED
> lpush li white
QUEUED
> exec
1) (error) WRONGTYPE Operation against a key holding the wrong kind of value
2) (integer) 4
> lrange li 0 10
1) "white"
2) "green"
3) "red"
4) "blue" # 所有的命令都执行了,只不过有的命令执行失败

注意点

  • redis的开启事务是将命令暂时保存在一个队列里,执行时依次操作;如果命令队列有一条出现语法错误,整个事务创建会失败;

  • redis没有提供事务的回滚功能,客户端必须自己处理失败的命令;

事务锁

# 基本命令
watch key key .. # 监控键值 # 取消对所有键的监控
unwatch
  • 由于redis的事务中的命令其实是缓存队列,并且redis可以防止在事务的执行过程中有其他的命令插入,即具有隔离性;但是在多个客户端进行并发操作时存在数据无法同步的问题;如客户端A、B同时操作键key的值加一,预期结果为增加2,实际可能只有1.

  • 为了解决这个问题,redis引入了watch监控键;

> watch num
OK
> set num 7
OK
> multi
OK
> set num 5
QUEUED
> exec
(nil)
> get num
"7"
  • 可以看到事务并没有执行成功,wetch可以监控键,如果在监控后,键的值发生了改变,那么redis后面与这个键相关的事务操作将会失败,同时在exec执行后,键的监控会被取消;

注意:无论监控多少个键或事务中有没有与该键相关的命令,在最近的一个执行了exec,无论事务执行有没有成功,watch监控的所有键都将会取消,后面的事务不再受影响。

说明:使用watch监控实现并发修改键值,如果事务被取消,需要手动重新执行事务;

问题

  • 以上可知,redis实现的是类似乐观锁(即预期并发时没有出现竞争修改同一个键值的状况),这种情况在并发量低时影响不大,但是高并发时几乎肯定出现竞争,并发修改键值程序重试的次数越来越多,资源被白白浪费,需要使用其他的方法实现悲观锁机制,这点后面会继续研究;
  • 作者:天宇之游
  • 出处:http://www.cnblogs.com/cwp-bg/
  • 本文版权归作者和博客园共有,欢迎转载、交流,但未经作者同意必须保留此段声明,且在文章明显位置给出原文链接。

redis基础之订阅发布、主从复制和事务(四)的更多相关文章

  1. 基于Redis消息的订阅发布应用场景

    目录 基于Redis消息的订阅发布应用场景 1.应用背景 2.困境 2.1 锁表风险 2.2 实时性差 2.3 增加编程复杂性 2.4 实时效果 3.解决方案 3.1 前端传值给服务端 3.2 服务端 ...

  2. Redis基础知识 之——发布/订阅

    一.说明: 订阅,取消订阅和发布实现了发布/订阅消息范式(引自wikipedia),发送者(发布者)不是计划发送消息给特定的接收者(订阅者).而是发布的消息分到不同的频道,不需要知道什么样的订阅者订阅 ...

  3. mysql主从复制、redis基础、持久化和主从复制

    一.mysql(mariadb)基础 1.基础命令(centos7操作系统下) 1.启动mysql systemctl start mariadb 2.linux客户端连接自己 mysql -uroo ...

  4. 基于Redis的消息订阅/发布

    在工业生产设计中,我们往往需要实现一个基于消息订阅的模式,用来对非定时的的消息进行监听订阅. 这种设计模式在 总线设计模式中得到体现.微软以前的WCF中实现了服务总线 ServiceBus的设计模式. ...

  5. python学习之-- redis模块管道/订阅发布

    redis 模块操作剩余其他常用操作 delete(*names):删除任意的数据类型exists(name):检测redis的name是否存在keys(pattern='*'):根据模型获取redi ...

  6. SpringBoot+Redis 实现消息订阅发布

    什么是 Redis Redis 是一个开源的使用 ANSI C语言编写的内存数据库,它以 key-value 键值对的形式存储数据,高性能,读取速度快,也提供了持久化存储机制. Redis 通常在项目 ...

  7. [SpingBoot guides系列翻译]Redis的消息订阅发布

    Redis的消息 部分参考链接 原文 CountDownLatch 概述 目的 这节讲的是用Redis来实现消息的发布和订阅,这里会使用Spring Data Redis来完成. 这里会用到两个东西, ...

  8. Redis的消息订阅/发布 Utils工具类

    package cn.cicoding.utils; import org.json.JSONException; import org.json.JSONObject; import redis.c ...

  9. python 实现redis订阅发布功能

    redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合).zset(sorted set ...

随机推荐

  1. 【GISER&&Painter】Chapter01:WebGL渲染初体验

    基于上一篇OpenGL的渲染原理,这两周又陆续接触了一些关于WebGL绘图的一些内容,因为刚入门,很多东西又很晦涩,所以特意花了小半天的时间整理了一下,特此记录. 零  画一个多边形吧! 把一个多边形 ...

  2. PAT 1033. To Fill or Not to Fill (贪心)

    PAT-A的最后一题,最终做出来了... 是贪心,通过局部最优获得全局最优. 1. 将加油站按距离升序排序 2. 记录当前所在的加油站index,存有的汽油,花费.向后遍历全部 该站可抵达的加油站 3 ...

  3. SVM 总结

    SVM有一个核心函数SMO,也就是序列最小最优化算法.SMO基本是最快的二次规划优化算法,其核心就是找到最优参数α,计算超平面后进行分类.SMO方法可以将大优化问题分解为多个小优化问题求解,大大简化求 ...

  4. [Javascript Crocks] Compose Functions for Reusability with the Maybe Type

    We can dot-chain our way to great success with an instance of Maybe, but there are probably cases wh ...

  5. Linux 内存泄露小结

    本文仅限记录自己的一次 内存泄露追踪小记. 可能并不十分适用与大家的情况.而且方法也并不是很smart.仅做记录,能提供个思路更好.        一. 要问调试程序遇到什么问题最头疼, 内存泄露肯定 ...

  6. Android 代码实现来电拦截

    为了更好地理解这个Demo,我先向大家介绍一下需求与功能. 需求: 每天都会有很多无聊的电话,比如推销商品等,占用我们大量时间不说,有时候还会打乱我们的思路,扰乱我们的正常生活.所以实现一个对某些号码 ...

  7. STL - C++ 11的Lambda表达式(上)

    Lambda始自C++ 11,是一种在表达式或语句内指定函数行为的定义式. 你可以定义函数行为作为对象,以inline实参的形式传给算法作为predicate(判断式). eg: std:transf ...

  8. webpack 通用模块(每个页面都用到的js)编译

    1.项目目录 2.配置文件:webpack.config.js var htmlWebpackPlugin = require('html-webpack-plugin'); var webpack ...

  9. css实现九宫格

    原理:浮动+margin负边距 示例代码: <!DOCTYPE html> <html lang="zh"> <head> <meta c ...

  10. 51CTO 资料汇总 截止20150504

    ================帖子列表,请大家选择自己喜欢的汇总贴分享================ 考试认证: 1.备战2014软考!精品视频教程推荐(综合复习+经验分享+考前冲刺)[随时更新] ...