前言
以前做过一个有关redis的技术分享,这里将之前分享的内容做了抽减,来大概的介绍一下redis,以帮助快速入门,对redis有个概要性的了解,不会做深入的介绍。本文中代码由于是直接用以前PPT上的截图,所以没有贴源码,请谅解。
本文内容如有错误的地方,欢迎指正。
Redis是什么?
Redis是完全开源免费、遵守BSD协议的一个高性能的key-value数据库。据官方统计数据:redis读 110000次/秒,写 81000次/秒。目前已经有很多公司都在用redis,下面举几个例子:
Redis的基本数据结构
Redis作为一个nosql数据库,支持五种基本的数据结构,可谓是相当丰富,能满足大部分使用场景。如下所示:
虽然说redis是nosql数据库,但是实际业务场景中,我们也可以用redis实现关系型表结构,这都跟上面的五种基本数据结构是分不开的。当然,这里只针对每种数据结构的底层做了提点,并没有去深入探究;redis的底层是用C/C++实现的,足以体现其高性能;在使用中,redis其实还对其底层结构做了一次封装,封装厂特有的对象,以便于上层的操作。感兴趣的可以去浏览一下redis的源码:https://github.com/antirez/redis
安全与性能
持久化
redis支持两种持久化方式:AOF 和 RDB(SNAPSHOTTING)。
RDB持久化也俗称快照,是将redis数据库中某一时刻的数据写入硬盘,存一个副本,然后在数据库数据丢失后,执行这个快照文件即可恢复数据。RDB的核心配置如下:
1 | save 60 1000 //60秒内有1000次更改操作则进行save |
AOF持久化是将操作命令追加到aof文件的末尾,以此来达到数据备份,即数据库崩溃时,可以重新执行这个文件,来尽可能的恢复数据。AOF的核心配置如下:
1 | appendonly yes //是否追加 |
下面来对RDB和AOF两种持久化方式做一个对比:
在实际应用中,基本上都是两种方式结合使用,这样能互相弥补缺点,尽量保证当出现数据丢失时达到最小。
事务
Redis的事务保证是通过WATCH、MULTI、EXEC、UNWATCH、DISCARD几个命令。下面给出一段代码(买卖关系)展示,主要讲几个命令综合起来运用,来探究redis事务。
这段代码很简单,当前,前提弄懂了这个几个命令的意思就更容易看懂了。
当然也可以通过非事务流水线来达到事务效果,即要么全部执行,要么全部不执行。非事务流水线应用也是很广的,下面贴出一段代码:也是通过MULTI和EXEC命令包裹执行的
集群
注:集群的两张图时参考其他资料借用而来的,由于看资料是很久以前,以不记得参考的资料的链接地址,故此未能贴出。
- 所有的redis节点彼此互联,内部使用二进制协议优化传输速度和带宽;
- 节点的fail是通过集群中超过半数的节点检测失效时才生效;
- 客户端与redis节点直连,不需要中间proxy,客户端不需要连接集群所有节点,连接集群中任何一个节点即可。
- redis-cluster把所有的物理节点映射到[0-16383]slot上(哈希槽,由cluster负责维护)
单个节点挂掉的情况:
- 所有master参与,如果半数以上master节点与其中一个master节点通信超时认为当前master节点挂掉。
整个集群不可用情况:
- 如果集群任意master挂掉,且当前master没有slave,集群进入fail状态,也可以理解成集群的slot映射[0- 16383]不完整时进入fail状态;
- 如果集群超过半数以上的master挂掉,无论是否有slave集群进入fail状态。
当然在实际业务场景中,运用redis集群并不是上诉这么简单,基本上都是要加中间件以及代理,网上已有很多大佬对此提出了方案。
Redis特性
原子性
原子性大致就一句话,要么全部执行,要么全都不执行。Redis的原子性体现在:
- Redis的所有操作都是原子性的;
- Redis支持几个操作的原子性执行 [ MULTI和EXEC命令包裹的操作]。
键的过期时间设定
1 | EXPIRE key-name seconds 设置多长时间后过期 |
发布与订阅
发布与订阅
SUBSCRIBE channel [channel …] 订阅频道
UNSUBSCRIBE channel [channel …] 退订频道
PUBLISH channel message 向给频道发送消息
PSUBSCRIBE pattern [pattern] 订阅与给定模式相匹配的所有频道
PUNSUBSCRIBE pattern [pattern …] 退订给定的模式
应用场景
String(可存储字符串、整数、浮点数)
- 原子计数器 [比如网站的点击量];
- 要对单个元素设置过期时间的情况下,只能使用String结构,不能使用哈希,因为hash的key不是redis的key;
- 字符串 [串的追加、获取子串]
- 二进制串的操作 [统计1的个数、按位操作等]
Hash
Hash可用于结构化存储,如下所示:
List
redis的list并不是传统上的list,它类似与双端队列or双向链表。举一些常见的例子:
- 最近联系人、最新评论、最新日志;
- 消息队列;
- 微博的时间线 [此方式也可用有序集合实现];
Set
这个结构的使用由于其结构的特性也很常见,比如:微博的共同关注、QQ的共同好友都可以用这种方式实现。
ZSet
此数据结构的特性是:带有权重、有序性。因此,可以用来做排行榜相关业务场景(比如投票、微博的热搜)。又因为其权重的特性(权重一样时,按值来排序),可以用来做英文的自动补全。
总结
Redis的基本数据结构有丰富的特性,可以在很多业务场景中使用,上面只是做一下提点,更多的需要我们在实际业务中思考去选择。笔者就喜欢用redis去解决实现一些业务场景,并且更喜欢用ZSet结构,这个结构很有魔性。
实际业务中,Redis觉大多数情况下都是用做缓存,且在缓存这方面,是可以完全替代Memcache的。
推荐资料
阿里开源 ApsaraCache :https://github.com/alibaba/ApsaraCache
资料链接:
- https://redis.io/
- https://redis.io/commands
- https://redis.io/documentation
- https://github.com/huangz1990/redis-3.0-annotated
- http://www.redis.cn
推荐如下两本书: