Redis核心数据结构
Redis核心数据结构
Redis 是一种开源(BSD 许可)、内存中数据结构存储,用作数据库、缓存和消息代理。底层使用c语言进行实现。Redis 提供了诸如字符串、散列、列表、集合、带范围查询的排序集合、位图、超级日志、地理空间索引和流等数据结构。
Redis内置复制、Lua 脚本、LRU 驱逐、事务和不同级别的磁盘持久化,并通过 Redis Sentinel 和 Redis Cluster 自动分区提供高可用性。
地址
GitHub:https://github.com/redis/redis
Redis数据类型简介:https://redis.io/topics/data-types-intro
命令完整列表:https://redis.io/commands
完整文档地址:https://redis.io/documentation
基本特性
- 非关系型的键值对数据库,可以根据键以O(1)的时间复杂度取出或插入关联值;
- 数据是存储在内存中的;
- 键值对中键的类型可以是字符串、整形、浮点型等,且键是唯一的,相同的键会覆盖值;
- 键值对中值类型可以是:String、Hash、List、Set、ZSet等 ;
- 内置了复制、磁盘持久化、LUA脚本、事务、SSL、ACLS、客户端缓存、客户端代理等功能;
- 提供了Redis哨兵、Redis cluster等高可用性的模式;
核心数据结构
String
String类型的结构对应JAVA的Map,key-val的存储形式
常用操作
命令 | 描述 |
---|---|
SET key value | 存入字符串 |
MSET [key val ...] | 批量存入字符串 |
GET key | 获取值 |
MGET [key ...] | 批量获取值 |
DEL [key ...] | 删除一个或多个键 |
EXPIRE key seconds | 设置一个键过期时间(s) |
SETNX key val | key不存在且保存成功返回1,失败返回0,可用做分布式锁 |
incrby key val | 批量生产序列号 |
SET key val EX 10 NX | 防止程序意外终止导致死锁 |
应用场景
- 单值缓存
- 对象缓存
- 分布式锁
- 计数器
- Web集群session共享
- 分布式系统全局系列号等
Hash
Hash类型的结构,存储一个类型的key-val
常用操作
命令 | 简述 |
---|---|
HASH key field value | 存储一个哈希表key的键值 |
HASHNX key field value | 存储一个不存在的哈希表key的键值 |
HMSET key field | 获取哈希表key对应的field键值 |
HMGET key [field ...] | 批量获取field键值 |
HDEL key [field ...] | 批量删除 |
HLEN key | 返回哈希表key中field的数量 |
HGETALL key | 返回哈希表key中所有的键值 |
HINCRBY key field increment | 为哈希表key中field键的值加上增量 |
应用场景
- 对象缓存
- 电商购物车等
优缺点
- 优点
- 同类数据归类整合储存,方便数据管理
- 相比String操作小号的内存与cpu更小
- 相比Stirng更节约存储空间
- 缺点
- 过期功能不能使用在field上,只能使用在key上
- Redis集群架构下不适合大规模使用
List
List,列表结构,跟JAVA中的List基本相似
命令 | 描述 |
---|---|
LPUSH key [value ...] | 将一个或多个value值插入到key列表的表头 |
RPUSH key [value ...] | 将一个或多value值插入多key列表表尾 |
LPOP key | 返回并移除key列表的头元素 |
RPOP key | 返回并移除key列表的尾元素 |
LRANGE key start stop | 返回列表key中制定区域内的元素,区间则以start和stop指定 |
BLPOP [key...] timeot | 从key列表表头弹出元素,若列表为空则阻塞等待,若timeout=0则一直阻塞 |
BRPOP [key...] timeout | 从key列表尾部弹出元素,若列表为空则阻塞等待,若timeout=0则一直阻塞 |
应用场景
- stack(栈) LPUSH + LPOP
- Queue (队列) LPUSH + RPOP
- Blocking MQ(阻塞队列)LPUSH + BRPOP
Set
Set集合,val中存储多个不重复的元素
常用命令
命令 | 描述 |
---|---|
SADD key [momber ...] | 往集合key中存入元素,元素存在则忽略 |
SREM key [momber ...] | 从集合key中删除元素 |
SMEMBERS key | 获取集合key中所有元素 |
SCARD key | 获取集合key的元素个数 |
SISMEMBER key momber | 判断val元素是否存在于key集合中 |
SRANDMENMBER key [count] | 从集合key中选出count个元素,元素不移除 |
SPOP key [count] | 从集合key中选出count个元素并移除元素 |
SINTER [key ..] | 交集运算 |
SINTERSTORE newSet [key ...] | 将交集结果存入新集合newSet中 |
SUNION [key ...] | 并集运算 |
SUNIONSTORE newSet [key ...] | 将并集结果存入新集合newSet中 |
SDIFF [key ... ] | 差集运算 |
SDIFFSTORE newSet [key ...] | 将差集结果存入新集合newSet中 |
应用场景
- 抽奖
- 去重
- 点赞/取消点赞
- 集合操作实现关注模型等
- 集合操作实现商品赛选等
ZSet
与Set集合类似,ZSet集合是有序的
命令 | 描述 |
---|---|
ZADD key [[score member] ...] | 往有序集合key中加入带分值元素 |
ZREM key [member ...] | 从有序集合key中删除元素 |
ZSCORE key member | 返回有序集合key中member元素的分值 |
ZINCRBY key increment member | 为key中元素member的分值加上increment |
ZCARD key | 返回key中的元素个数 |
ZRANGE key start stop [withscores] | 正序获取key中start到stop的元素 |
ZREVRANGE key start stop [withscores] | 倒序获取key中start到stop的元素 |
应用场景
- 微博排行榜
- 七日排行榜单等
Redis的单线程和高性能
- Redis的单线程并非是真正意义上的单线程。单线程主要是指网络IO和键值对读写是由一个线程来完成,而这也是Redis对外提供键值存储服务的主要流程。Redis内部的其他功能,例如持久化、 异步删除、数据同步等等是会有额外的线程去执行的。
- 单个线程访问之所以还会那么快,是因为数据都存在内存中,所有的运算都是内存级别的运算,单线程同时避免了多线程所带来的上下文切换问题。
- 单线程的任务我们需要注意访问的命令,对于那些耗时的命令以及当访问一个bigkey的时候可能会导致Redis卡顿。
- 对于客户端的并发连接,Redis底层利用epoll模型来实现IO多路复用,将链接信息和时间放到队列中,依次放到文件事件分派器,事件分派器将事件分发给对应的事件处理器。
其他高级命令
keys
全局遍历所有的key,用来列出所有满足特定正则字符串规则的key,当Redis数据量较大时,性能会有所下降,应避免使用
scan
SCAN cursor [MATCH pattern] [COUNT count] 渐进式便利所有的键,相对于keys性能消耗更小,安全性更低
scan 参数提供了三个参数,第一个是 cursor 整数值(hash桶的索引值),第二个是 key 的正则模式,第三个是一次遍历的key的数量(参考值,底层遍历的数量不一定),并不是符合条件的结果数量。第一次遍历时,cursor 值为 0,然后将返回结果中第一个整数值作为下一次遍历的 cursor。一直遍历到返回的 cursor 值为 0 时结束。
⚠️注意:scan并非完美无瑕,如果在scan的过程中如果有键的变化(增加、 删除、 修改),那么遍历效果可能会碰到如下问题:
新增的键可能没有遍历到,遍历出了重复的键等情况,也就是说scan并不能保证完整的遍历出来所有的键,这些是我们在开发时需要考虑的。
info
查看Redis服务运行信息,分为以下9大块:
- Server: 服务器运行的环境参数
- Clients: 客户端相关信息
- Memory: 服务器运行内存统计数据
- Persistence: 持久化信息
- Stats: 通用统计数据
- Replication: 主从复制相关信息
- CPU: CPU使用情况
- Cluster: 集群情况
- KeySpace: 键值对统计数量信息