Redis面试题之Redis基本数据类型和高级数据类型
文章目录
- Redis是什么
- Redis常用的数据类型及每种类型应用场景
- 2.1 常用的5种基本数据类型
- 2.1.1 String类型
- 2.1.2 Hash
- 2.1.3 List
- 2.1.4 Set
- 2.1.5 Zset
- 2.2 Redis的高级数据类型
- 2.2.1 Bitmaps
- 2.2.2 HyperLogLog
- 2.2.3 GEO
- 为什么要用Redis
- 3.1 高性能
- 3.2 解决并发
- Redis为何这么快
- 4.1 那Redis这么快, 那它是什么线程模式呢
- 4.2 Redis和Memcached的区别
1. Redis是什么
Redis 是 C 语言开发的一个开源的(遵从 BSD 协议)高性能键值对(key-value)的内存数据库,可以用作数据库、缓存、消息中间件等。
它是一种 NoSQL(not-only sql,泛指非关系型数据库)的数据库。
Redis的特征:
- 数据间没有必然的关联关系
- 内部采用单线程机制进行工作
- 高性能。官方提供测试数据,50个并发执行100000 个请求,读的速度是110000 次/s,写的速度是81000次/s。
- 多数据类型支持
字符串类型 string
列表类型 list
散列类型 hash
集合类型 set
有序集合类型 sorted_set(zset) - 持久化支持。可以进行数据灾难恢复
Redis 的应用
- 为热点数据加速查询(主要场景),如热点商品、热点新闻、热点资讯、推广类等高访问量信息等
- 任务队列,如秒杀、抢购、购票排队等
- 即时信息查询,如各位排行榜、各类网站访问统计、公交到站信息、在线人数信息(聊天室、网站)、设
备信号等 - 时效性信息控制,如验证码控制、投票控制等
- 分布式数据共享,如分布式集群架构中的 session 分离
- 消息队列
- 分布式锁
2. Redis常用的数据类型及每种类型应用场景
2.1 常用的5种基本数据类型
刚才有提到Redis常用的5种数据类型, 在具体介绍前,我们先来了解下Redis内部内存管理是如何描述这5种数据类型的.
首先Redis内部使用一个redisObject对象来表示所有的key和value.
redisObject最主要的信息如上图所示: type表示一个value对象具体是何种数据类型, encoding是不同数据类型在Redis内部的存储方式.
比如:type=string 表示 value 存储的是一个普通字符串,那么 encoding 可以是 raw 或者 int.
这里说下,数据类型是针对Value的, Redis是key=value格式存储的,Key都是一样的是String类型的, Value有不同数据类型, 接下来,我们简单介绍下这常用的5中数据类型~
2.1.1 String类型
String是Redis最基本的类型, 可以与内存存储一模一样的类型, 一个Key对应一个Value. Value不仅String类型的, 也可以是数字.
String 类型是二进制安全的,意思是 Redis 的 String 类型可以包含任何数据,比如 jpg 图片或者序列化的对象, String 类型的值最大能存储 512M.
- 应用场景
- 缓存功能:String字符串是最常用的数据类型, 不仅仅是Redis, 各个语言都是最基本类型,因此,利用Redis作为缓存,配合其它数据库作为存储层,利用Redis支持高并发的特点,可以大大加快系统的读写速度、以及降低后端数据库的压力。
- 计数器:许多系统都会使用Redis作为系统的实时计数器,可以快速实现计数和查询的功能。而且最终的数据结果可以按照特定的时间落地到数据库或者其它存储介质当中进行永久保存。
- 共享用户Session:用户重新刷新一次界面,可能需要访问一下数据进行重新登录,或者访问页面缓存Cookie,但是可以利用Redis将用户的Session集中管理,在这种模式只需要保证Redis的高可用,每次用户Session的更新和获取都可以快速完成。大大提高效率。
2.1.2 Hash
Hash是一个键值(key-value)的集合。Redis 的 Hash 是一个 String 的 Key 和 Value 的映射表,Hash 特别适合存储对象。常用命令:hget,hset,hgetall 等。
- 应用场景:可以封装对象格式的数据
2.1.3 List
List 列表是简单的字符串列表(双向列表), 按照插入顺序排序, 可以添加一个元素到列表的头部(左边)或者尾部(右边) 常用命令:lpush、rpush、lpop、rpop、lrange(获取列表片段)等。
- 应用场景:
- 链表特点查询快, 可以作为消息队列使用.
- 用户的粉丝列表
- 博客首页,博主的文章列表
2.1.4 Set
Set 是无序不可重复的, 底层是通过 hashtable 实现的, 常用命令:sdd、spop、smembers、sunion 等。
- 应用场景:
- 和List一样,区别在于 Set 是自动去重. 而且 Set 提供了判断某个成员是否在一个 Set 集合中, 比如: 统计访问网站的所有Ip.
- 可以基于 Set 玩儿交集、并集、差集的操作,比如交集吧,我们可以把两个人的好友列表整一个交集,看看俩人的共同好友是谁?
2.1.5 Zset
Zset 特点是有序且不可重复。常用命令:zadd、zrange、zrem、zcard 等。
- 应用场景:
- 排行榜:有序不重复数据类型典型应用场景做排行榜. 例如视频网站需要对用户上传的视频做排行榜,榜单维护可能是多方面:按照时间、按照播放量、按照获得的赞数等。
- 用Zset来做带权重的队列,比如普通消息的score为1,重要消息的score为2,然后工作线程可以选择按score的倒序来获取工作任务, 让重要的任务优先执行.
2.2 Redis的高级数据类型
2.2.1 Bitmaps
Bitmaps是应用于位运算来存储数据, 主要应用场景是应用于信息转态的统计, 即某个数据是黑或白的问题, 没有多个选项.
基本操作
- 设置数据
setbit key [位移数 value] 注意: value只能是1或0.
- 获取数据
getbit key 位移数
- 统计对应key 有多少个value为1的数据
bitcount key
- 设置数据
高级操作
- 对特定key按位进行交, 并, 非, 异或操作, 并将结果保存到合同后的key中
bitop and(交)/or(并)/not(非)/xor(异或) 新key 旧key1 旧key2
- 对特定key按位进行交, 并, 非, 异或操作, 并将结果保存到合同后的key中
应用场景, 信息状态的统计
比如电影网站,- 统计每天某一部电影是否被点播, =>只要找到对应的key, 知道他的位移位置, 看看是不是1就知道是否被点播过了.
- 统计每天有多少部电影被点播, =>每天的数据进行bitcount就可以了.
- 统计每周/月/年有多少部电影被点播, =>把每天的数据进行or运算, 都为1代表这个电影被点过了, 为0则代表从来没有被点过.
- 统计年度哪部电影没有被点播. =>把每天的数据进行or运算, 都为1代表这个电影被点过了, 为0则代表从来没有被点过.
- 统计每天某一部电影是否被点播, =>只要找到对应的key, 知道他的位移位置, 看看是不是1就知道是否被点播过了.
2.2.2 HyperLogLog
HyperLogLog存储的数据也是普通的字符串, 但是它有个特点是能够用来做基数统计(基数就是数据集去重后元素个数), 运用了LogLog的算法来去重. 主要应用场景用于独立信息统计.
基本操作
- 添加数据:
pfadd key [element1, element2 ...] pfadd a 1 2 2
- 统计数据:
pfcount key
- 合并数据:
pfmerge 新key [旧key1, 旧key2...]
- 添加数据:
应用场景
- 用于进行基数统计,不是集合,不保存数据,只记录数量而不是具体数据
- 核心是基数估算算法,最终数值存在一定误差
- 误差范围:基数估计的结果是一个带有 0.81% 标准错误的近似值
- 耗空间极小,每个hyperloglog key占用了12K的内存用于标记基数
- pfadd命令不是一次性分配12K内存使用,会随着基数的增加内存逐渐增大
- pfmerge命令合并后占用的存储空间为12K,无论合并之前数据量多少
2.2.3 GEO
类似于微信啊, 陌陌等社交软件都有搜索附件的人, 那么地理位置如何计算出来的呢?这就可以应用Redis的geo数据类型了. 不过GEO计算的是水平距离, 没有办法加上垂直距离.
- 基本操作
- 添加坐标点
geoadd key 横坐标 纵坐标 坐标点名称
- 计算坐标点经纬度
geohash key 坐标点名称
- 计算两个坐标点距离
geodist key 坐标点名称a 坐标点名称b 单位
- 添加坐标点
- 应用场景
主要应用于计算坐标点及多个坐标点直接的水平距离.
3. 为什么要用Redis
Redis是一种非关系型数据库, 经常和Mysql结合使用, 在项目中作为缓存数据库使用. 如果大家想了解其他非关系型数据库详见博主上篇文章常见的非关系型数据库有哪些
3.1 高性能
- 假如用户第一次访问数据库中的某些数据. 这个过程会比较慢, 因为是从硬盘上读取的. 将该用户访问的数据存在数缓存中,这样下一次再访问这些数据的时候就可以直接从缓存中获取了。
- 操作缓存就是直接操作内存,所以速度相当快。如果数据库中的对应数据改变的之后,同步改变缓存中相应的数据即可!
3.2 解决并发
- 直接操作缓存能够承受的请求是远远大于直接访问数据库的,所以我们可以考虑把数据库中的部分数据转移到缓存中去,这样用户的一部分请求会直接到缓存这里而不用经过数据库。
4. Redis为何这么快
- 官方提供的数据可以达到 100000+ 的 QPS(每秒内的查询次数),这个数据不比 Memcached(内存直接查询) 差!
4.1 那Redis这么快, 那它是什么线程模式呢
- Redis确实是单进程单线程的模型, 因为Redis完全是基础内存操作, CPU不是Redis的瓶颈, Redis的瓶颈最有可能是机器内存的大小或网络带宽.
- 那疑问又来了, 既然Redis是单线程的, 那么为什么还能这么快呢?
- Redis完全基于内存, 绝大部分请求是纯粹的内存操作, 非常速度, 数据存在内存中.
- 采用单线程, 避免了不必要的上下文切换和竞争条件, 不存在多线程导致的CPU切换, 不用去考虑各种锁的问题, 不存在加锁释放锁操作, 没有死锁问题导致的性能消耗.
- 使用多路复用IO模型, 非阻塞IO, 每一条线程有自己的IO模型.
4.2 Redis和Memcached的区别
刚才对于Redis为什么这么快说了很多, 主要原因还是数据存在内存里面, 那么问题又来了, 为什么选择Redis的缓存方案而不用Memcached呢?
- 存储方式上:Memcache 会把数据全部存在内存之中,断电后会挂掉,数据不能超过内存大小。Redis 有部分数据存在硬盘上,这样能保证数据的持久性。
- 数据支持类型上:Memcache 对数据类型的支持简单,只支持简单的 key-value,而 Redis 支持五种数据类型。
- 使用底层模型不同:它们之间底层实现方式以及与客户端之间通信的应用协议不一样。Redis 直接自己构建了 VM 机制,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求。
- Value 的大小:Redis 可以存储达到 1GB,而 Memcache 只有 1MB。
还没有评论,来说两句吧...