前面已经学习了redis的基本的命令行操做和数据类型,下面开始redis一些有趣的功能。redis
定义:发布者至关于电台,订阅者至关于客户端,客户端发到频道的消息,将会被推送到全部订阅此频道的客户端;客户端不须要主动去获取消息,只须要订阅频道,这个频道的内容就会被推送过来;数据库
做用:发布者和订阅者的解耦合能够带来更大的扩展性和更加动态的网络拓扑;缓存
# 订阅消息 subscribe 频道1 频道2 # 此时redis客户端会一直处于监听频道的状态,一有消息就处理; # 取消订阅 unsubcribe 频道1 ... # 若是不写频道名称,则取消全部的订阅; # 推送消息 publish 频道1 消息内容
发布订阅机制通常使用在对同一个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负责写,也能够读;从服务器只能读,不能写;
方式二:使用命令行的方式动态设置spa
# 从服务器链接主服务器 slaveof host port # 从服务器断开主服务器 slaveof no one
重要说明
从服务器与主服务器进行初始链接时,从服务器会丢弃全部的旧数据,而后载入主服务器的数据;
redis不支持主主复制,也就是说不能够两个redis相互设置对方为主服务器,虽然不会报错,但性能方面,以及对客户端的请求均可能出现问题;
等待从服务器的命令进入-->执行bgsave,建立快照文件;使用缓存区记录bgsave命令执行后全部的写命令-->快照文件建立完毕后,向服务器发送快照文件-->发送快照文件完毕后向从服务器发送缓存区的写命令-->完毕后每收到一个写命令就向从服务器发送
链接主服务器,发送sync命令-->等待响应-->丢弃全部的旧数据,载入主服务器的快照文件-->完成快照文件的解释,开始接受命令请求-->执行从主服务器发送的全部的写命令;
注意:redis支持主从链,即从服务器还能够有从服务器,可是从服务器A复制从服务器B的过程和从服务器B复制主服务器是有区别的;从服务器B向从服务器A发送完毕快照文件后,会先断开与从服务器A的链接,从服务器A须要从新链接而且请求同步;
redis有像关系型数据库同样的事务机制来保证多条命令做为原子操做;事务中的命令要么全执行,要么全不执行;
事务的完整过程:开始事务-->命令进入缓存-->执行事务;
# 开启一个事务 multi # 提交命令后,redis会将后面的操做保存起来 # 提交事务 exec # 提交命令后,redis会执行前面保存的全部的命令 # 取消事务 discard # 若是书写命令队列的过程当中须要取消事务时使用
> 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" # 全部的命令都没有执行
> 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"
注意:不管监控多少个键或事务中有没有与该键相关的命令,在最近的一个执行了exec,不管事务执行有没有成功,watch监控的全部键都将会取消,后面的事务再也不受影响。
说明:使用watch监控实现并发修改键值,若是事务被取消,须要手动从新执行事务;
问题