1.什么是Redis
Redis(Remote Dictionary Server),即远程字典服务,是一个开源,内存存储的数据结构服务器,可用作数据库,高速缓存和消息队列代理。它支持字符串、哈希表、列表、集合、有序集合,位图,hyperloglogs等数据类型。内置复制、Lua脚本、LRU收回、事务以及不同级别磁盘持久化功能,同时通过Redis Sentinel提供高可用,通过Redis Cluster提供自动分区。
数据库分为关系型数据库(RDBMS)和非关系型数据库(NoSQL)
关系型数据库(RDBMS)和非关系型数据库(NoSQL)对比:
RDBMS:
- 组织化结构
- 固定SQL
- 数据和关系都存在单独的表中(行列)
- DML(数据操作语言)、DDL(数据定义语言)等
- 严格的一致性(ACID): 原子性、一致性、隔离性、持久性
- 基础的事务
NoSQL:
- 不仅仅是数据
- 没有固定查询语言
- 键值对存储(redis)、列存储(HBase)、文档存储(MongoDB)、图形数据库(不是存图形,放的是关系)(Neo4j)
- 最终一致性(BASE):基本可用、软状态/柔性事务、最终一致性
2.Redis五大基本类型
Redis存储的是key-value结构的数据,其中key是字符串类型,value有五种常用的数据类型:
- 字符串
string:普通字符串,Redis中最简单的数据类型 - 哈希
hash:也叫散列,类似于java中的HashMap结构 - 列表
list:按照插入顺序排序,可以有重复元素,类似于java中的LinkedList - 集合
set:无序集合,没有重复元素,类似于java中的HashSet - 有序集合
sorted set/zset:集合中每个元素关联一个分数(score),根据分数升序排序,没有重复元素
2.1 字符串string
Redis字符串类型常用命令:
SET key value:设置指定key的值。eg:set name qingGET key:获取指定key的值。eg:get nameSETEX key seconds value:设置指定key的值,并将key的过期时间设为seconds秒。eg:setex code 30 abcSETNX key value:只有在key不存在时设置key的值。eg:setnx name qing
字符串类型应用场景:
- 缓存功能:String字符串是最常用的数据类型,不仅仅是redis,各个语言都是最基本类型,因此,利用redis作为缓存,配合其它数据库作为存储层,利用redis支持高并发的特点,可以大大加快系统的读写速度、以及降低后端数据库的压力
- 计数器:许多系统都会使用redis作为系统的实时计数器,可以快速实现计数和查询的功能。而且最终的数据结果可以按照特定的时间落地到数据库或者其它存储介质当中进行永久保存
- 共享用户session:用户重新刷新一次界面,可能需要访问一下数据进行重新登录,或者访问页面缓存cookie,这时可以利用redis将用户的session集中管理,在这种模式只需要保证redis的高可用,每次用户session的更新和获取都可以快速完成。大大提高效率。
2.2 哈希hash
Redis hash是一个string类型的filed和value的映射表,hash特别适合用于存储对象,常用命令如下:
HSET key field value:将哈希表key中的字段field的值设为valueHGET key field:获取存储在哈希表中指定字段的值HDEL key field:删除存储在哈希表中的指定字段HKEYS key:获取哈希表中所有字段(获取field1、field2)HVALS key:获取哈希表中所有值(获取value1、value2)
哈希类型应用场景:
- 由于hash数据类型的key-value的特性,用来存储关系型数据库中表记录,是redis中哈希类型最常用的场景。一条记录作为一个key-value,把每列属性值对应成field-value存储在哈希表当中,然后通过key值来区分表当中的主键
- 经常被用来存储用户相关信息。优化用户信息的获取,不需要重复从数据库当中读取,提高系统性能
2.3 列表list
Redis列表是简单的字符串列表,按照插入顺序排序,常用命令如下:
LPUSH key value1 [value2]:将一个或多个值插入到列表头部LRANGE key start stop:获取列表指定范围内的元素RPOP key:移除并获取列表最后一个元素LLEN key:获取列表长度
列表类型应用场景:
- 消息队列:reids的链表结构,可以轻松实现阻塞队列,可以使用左进右出的命令组成来完成队列的设计
- 文章列表或者数据分页展示的应用。比如,我们常用的博客网站的文章列表,当用户量越来越多时,而且每一个用户都有自己的文章列表,而且当文章多时,都需要分页展示,这时可以考虑使用redis的列表,列表不但有序同时还支持按照范围内获取元素,可以完美解决分页查询功能
2.4 集合set
Redis set是string类型的无序集合,集合成员是唯一的,集合中不能出现重复的数据,常用命令如下:
SADD key member1 [member2]:向集合添加一个或多个成员SMEMBERS key:返回集合中的所有成员SCARD key:获取集合的成员数SINTER key1 [key2]:返回所有给定集合的交集SUNION key1 [key2]:返回所有给定集合的并集SREM key member1 [member2]:删除集合中一个或多个成员
集合类型应用场景:
- 标签:比如博客网站常常使用到的兴趣标签,把一个个有着相同爱好,关注类似内容的用户利用一个标签把他们进行归并
- 共同好友功能,共同喜好,或者可以引申到二度好友之类的扩展应用
- 统计网站的独立IP。利用set集合当中元素不唯一性,可以快速实时统计访问网站的独立IP
2.5 有序集合sorted set/zset
Redis有序集合是string类型元素的集合,且不允许有重复成员,每个元素都会关联一个double类型的分数,常用命令如下:
ZADD key score1 member1 [score2 member2]:向有序集合添加一个或多个成员ZRANGE key start stop [WITHSCORES]:通过索引区间返回有序集合中指定区间内的成员ZINCRBY key increment member:有序集合中对指定成员的分数加上增量incrementZREM key member [member...]:移除有序集合中的一个或多个成员
有序集合应用场景:
- 排行榜:有序集合经典使用场景。例如视频网站需要对用户上传的视频做排行榜,榜单维护可能是多方面:按照时间、按照播放量、按照获得的赞数等
- 用Sorted Sets来做带权重的队列,比如普通消息的score为1,重要消息的score为2,然后工作线程可以选择按score的倒序来获取工作任务,让重要的任务优先执行
3.Redis三大特殊类型
除了 5 种基本的数据结构之外,Redis 还支持 3 种特殊的数据结构:Bitmap、HyperLogLog、GEO
3.1 位存储Bitmap
Bitmap 存储的是连续的二进制数字(0 和 1),通过 Bitmap, 只需要一个 bit 位来表示某个元素对应的值或者状态,key 就是对应元素本身 。我们知道 8 个 bit 可以组成一个 byte,所以 Bitmap 本身会极大的节省储存空间。
可以将 Bitmap 看作是一个存储二进制数字的数组,数组中每个元素的下标叫做 offset(偏移量)
常用命令如下:
SETBIT key offset value: 设置指定 offset 位置的值GETBIT key offset: 获取指定 offset 位置的值BITCOUNT key start end: 获取 start 和 end 之前值为 1 的元素个数BITOP operation destkey key1 key2 ...:对一个或多个 Bitmap 进行运算,可用运算符有 AND, OR, XOR 以及 NOT
使用场景:需要保存状态信息(0/1 即可表示)的场景,如:
- 用户签到情况、活跃用户情况、用户行为统计(比如是否点赞过某个视频)
3.2 基数HyperLogLog
HyperLogLog 是一种有名的基数计数概率算法 ,基于 LogLog Counting(LLC)优化改进得来,并不是 Redis 特有的,Redis 只是实现了这个算法并提供了一些开箱即用的 API,相关命令如下:
PFADD key element1 element2 ...:添加一个或多个元素到 HyperLogLog 中PFCOUNT key1 key2:获取一个或者多个 HyperLogLog 的唯一计数PFMERGE destkey sourcekey1 sourcekey2 ...:将多个 HyperLogLog 合并到 destkey 中,destkey 会结合多个源,算出对应的唯一计数
使用场景:数量量巨大(百万、千万级别以上)的计数场景,如:
- 热门网站每日/每周/每月访问 ip 数统计、热门帖子 uv 统计
3.3 地理位置Geospatial
主要用于存储地理位置信息,基于 Sorted Set 实现。通过 GEO 我们可以轻松实现两个位置距离的计算、获取指定位置附近的元素等功能,常用命令如下:
GEOADD key longitude1 latitude1 member1 ...: 添加一个或多个元素对应的经纬度信息到 GEO 中GEOPOS key member1 member2 ...: 返回给定元素的经纬度信息GEODIST key member1 member2 M/KM/FT/MI:返回两个给定元素之间的距离GEORADIUS key longitude latitude radius distance:获取指定位置附近 distance 范围内的其他元素,支持 ASC(由近到远)、DESC(由远到近)、Count(数量) 等参数GEORADIUSBYMEMBER key member radius distance:类似于 GEORADIUS 命令,只是参照的中心点是 GEO 中的元素
应用场景:需要管理使用地理空间数据的场景,如:
- 查看附近的人
- 微信位置共享
- 地图上直线距离的展示
4.Redis事务
Redis事务就是一次性、顺序性、排他性的执行一个队列中的一系列命令
数据库事务:
-
数据库事务通过ACID(原子性、一致性、隔离性、持久性)来保证。
-
数据库中除查询操作以外,插入(Insert)、删除(Delete)和更新(Update)这三种操作都会对数据造成影响,因为事务处理能够保证一系列操作可以完全地执行或者完全不执行,因此在一个事务被提交以后,该事务中的任何一条SQL语句在被执行的时候,都会生成一条撤销日志(Undo Log)。
Redis事务:
-
Redis事务就是一次性、顺序性、排他性的执行一个队列中的一系列命令
-
Redis事务的三个阶段:1.开始事务 2.命令入队 3.执行事务
-
一组命令中存在两种错误不同处理方式:
- 代码语法错误(编译时异常)所有命令都不执行
- 代码逻辑错误(运行时错误),其他命令可以正常执行 (该点不保证事务的原子性)
-
Redis事务不支持回滚机制