Redis的常用技术
一.Redis事务
Redis支持事务管理,尽管Redis事务没有数据库事务那么强大,但是某些场合下,使用redis事务代替数据库事务,那么可以保证数据一致性的同时大幅提高性能。
Redis提供事务管理,是为了解决并发情况下数据一致性的问题,Redis事务使用multi-exec命令组合,使用它可以保证:
1)事务是一个被隔离的操作,事务中的操作都会被Redis序列化并按顺序执行,在事务执行的过程中不会被其他客户端的命令打断。
2)事务是一个原子操作,要么全部执行,要么全不执行。
在Redis中事务基本上经历三个过程:开启事务》命令进入队列》执行事务。
先列出事务的基本操作:
命令 | 说明 | 备注 |
multi | 开启事务命令,之后的命令操作进入队列而不会马 上执行。 | |
watch key1 [key2...] | 监听某些键,如果被监听的键在事务执行前被修改, 则事务会被回滚 | 使用乐观锁,watch命令要写在multi命令之 前。 |
unwatch key1 [key2...] | 取消监听某些键 | |
exec | 执行事务 | 在执行事务队列存储的命令之前,Redis会 检测被监听的键值对有没有发生变化,如果 没有则执行命令,如果发生变化就回滚事务 |
discard | 回滚事务 | 执行回滚命令之后就不能再用exec命令提 交事务。 |
看起来Redis事务命令十分简单,而实际上也确实如此。下面我们来分析Redis事务的流程:
当我们写下multi并按下回车之后,就意味着我们接下来的命令不会立即执行,而是会被Redis添加到一个事务命令队列,直到以下情况出现:
1)Redis遇到了格式不正确的命令:Redis会检查每一个要进入事务命令队列的命令,如果这个命令不符合Redis规范,那么Redis会立即进行报错,并且整个事务都不会被执行(或者说事务回滚了)。
2)Redis遇到了discard命令:当Redis检测到discard命令的时候,会对事务进行回滚,在此之后,如果再遇到exec命令会进行报错。
3)Redis遇到了exec命令:exec命令触发了事务的执行,接下来,事务会先进行键值对检查,检查那些被监听的键值对是否出现了变化,如果出现变化,事务回滚并取消对相应键值对的监控;如果没有发生变化,事务执行并取消监控。至此,一个事务就彻底执行完毕。
另外需要注意的是:Redis只会检查命令语法是否合乎规范,不会对命令的数据类型进行检查。
Redis的事务流程我们已经清楚了,那么Redis是通过什么来保证并发情况下的数据一致性呢?Redis参考了CAS(比较与交换)机制,CAS原理请参考博客:http://blog.csdn.net/hsuxu/article/details/9467651,但是Redis又不是完全采用了CAS原理,因为CAS原理存在一个ABA问题。Redis的机制不会产生ABA问题,而且其多个事务完全可以在非阻塞的多线程环境中并发执行。
二.流水线技术
Redis的流水线技术是一种通信协议,可以通过java来调用jedis包中相应的方法。
三.发布订阅模式
观察者模式是这个模式的典型应用,生活中的应用类似于银行的交易信息通知,支付宝交易提示等。
在一个客户端1写下通过subscribe chat命令用来订阅chat渠道。
在另一个客户端2写下publish chat message发布chat渠道的message信息。
这时候就可以再客户端1看到由客户端2发布的消息。
四.超时命令
Redis基于内存,而内存资源在计算机中十分宝贵,所以对于Redis键值对的内存回收也是一个十分重要的问题。我们可以使用del手动删除一部分键值对,与此同时,当内存空间满了之后,它还会按照回收机制去自动回收一些键值对。
在谈论Redis的内存回收之前,首先讨论键值对的超时命令,对于Redis而言,可以给对应的键值对设置超时:
命令 | 说明 | 备注 |
persist key | 持久化key,取消超时时间 | 移除key的超时时间 |
ttl key | 查看key的超时时间 | 以秒为单位,-1代表没有超时时间,如果不存在key或者key已经超时则为-2 |
expire key seconds | 设置超时时间戳 | 以秒为单位 |
expireat key timestamp | 设置超时时间点 | 用uninx时间戳确定 |
pptl key milliseconds | 查看key的超时时间戳 | 以毫秒为单位 |
pexpire key | 设置键值超时的时间 | 以毫秒为单位 |
pexpireat key stamptimes | 设置超时时间点 | 以毫秒为单位的uninx时间戳 |
下面我们来讨论一个问题:如果一个key超时了,Redis会回收key的存储空间么?
答案是不会:Redis的key超时不会被自动回收,它只会标识哪些键值对超时了。好处:如果一个很庞大的数据结构,立即回收会造成Redis停顿并浪费大量时间。坏处:超时的key占用了大量内存空间。
Redis提供两种方式来回收这些键值对:
1)定时回收:在某一个确定的时间点触发一次回收代码,回收超时键值对。可以完全回收超时的键值对,但是耗费时间,也会导致Redis停顿,所以通常选择一个没有业务的时间点进行回收。
2)惰性回收:当一个超时的键再次用get命令访问的时候,触发Redis回收该键值对。可以指定要回收的键值对,但是要执行一次get操作。