详解 Redis 面试题(一)




什么是Redis

Redis(Remote Dictionary Server) 是一个使用 C 语言编写的,开源的(BSD许可)高性能非关系型(NoSQL)的键值对数据库。前端

Redis 能够存储键和五种不一样类型的值之间的映射。键的类型只能为字符串,值支持五种数据类型:字符串、列表、集合、散列表、有序集合。web

与传统数据库不一样的是 Redis 的数据是存在内存中的,因此读写速度很是快,所以 redis 被普遍应用于缓存方向,每秒能够处理超过 10万次读写操做,是已知性能最快的Key-Value DB。另外,Redis 也常常用来作分布式锁。除此以外,Redis 支持事务 、持久化、LUA脚本、LRU驱动事件、多种集群方案。redis

Redis有哪些优缺点

优势数据库

  • 读写性能优异, Redis能读的速度是110000次/s,写的速度是81000次/s。后端

  • 支持数据持久化,支持AOF和RDB两种持久化方式。缓存

  • 支持事务,Redis的全部操做都是原子性的,同时Redis还支持对几个操做合并后的原子性执行。服务器

  • 数据结构丰富,除了支持string类型的value外还支持hash、set、zset、list等数据结构。微信

  • 支持主从复制,主机会自动将数据同步到从机,能够进行读写分离。数据结构

缺点多线程

  • 数据库容量受到物理内存的限制,不能用做海量数据的高性能读写,所以Redis适合的场景主要局限在较小数据量的高性能操做和运算上。

  • Redis 不具有自动容错和恢复功能,主机从机的宕机都会致使前端部分读写请求失败,须要等待机器重启或者手动切换前端的IP才能恢复。

  • 主机宕机,宕机前有部分数据未能及时同步到从机,切换IP后还会引入数据不一致的问题,下降了系统的可用性。

  • Redis 较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂。为避免这一问题,运维人员在系统上线时必须确保有足够的空间,这对资源形成了很大的浪费。

为何要用 Redis /为何要用缓存

主要从“高性能”和“高并发”这两点来看待这个问题。

高性能:

假如用户第一次访问数据库中的某些数据。这个过程会比较慢,由于是从硬盘上读取的。将该用户访问的数据存在数缓存中,这样下一次再访问这些数据的时候就能够直接从缓存中获取了。操做缓存就是直接操做内存,因此速度至关快。若是数据库中的对应数据改变的以后,同步改变缓存中相应的数据便可!

高并发:

直接操做缓存可以承受的请求是远远大于直接访问数据库的,因此咱们能够考虑把数据库中的部分数据转移到缓存中去,这样用户的一部分请求会直接到缓存这里而不用通过数据库。

为何要用 Redis 而不用 map/guava 作缓存?

缓存分为本地缓存和分布式缓存。以 Java 为例,使用自带的 map 或者 guava 实现的是本地缓存,最主要的特色是轻量以及快速,生命周期随着 jvm 的销毁而结束,而且在多实例的状况下,每一个实例都须要各自保存一份缓存,缓存不具备一致性。

使用 redis 或 memcached 之类的称为分布式缓存,在多实例的状况下,各实例共用一份缓存数据,缓存具备一致性。缺点是须要保持 redis 或 memcached服务的高可用,整个程序架构上较为复杂。

Redis为何这么快

一、彻底基于内存,绝大部分请求是纯粹的内存操做,很是快速。数据存在内存中,相似于 HashMap,HashMap 的优点就是查找和操做的时间复杂度都是O(1);

二、数据结构简单,对数据操做也简单,Redis 中的数据结构是专门进行设计的;

三、采用单线程,避免了没必要要的上下文切换和竞争条件,也不存在多进程或者多线程致使的切换而消耗 CPU,不用去考虑各类锁的问题,不存在加锁释放锁操做,没有由于可能出现死锁而致使的性能消耗;

四、使用多路 I/O 复用模型,非阻塞 IO;

五、使用底层模型不一样,它们之间底层实现方式以及与客户端之间通讯的应用协议不同,Redis 直接本身构建了 VM 机制 ,由于通常的系统调用系统函数的话,会浪费必定的时间去移动和请求;

数据类型

Redis有哪些数据类型

Redis主要有5种数据类型,包括String,List,Set,Zset,Hash,知足大部分的使用要求

数据类型 能够存储的值 操做 应用场景
STRING 字符串、整数或者浮点数 对整个字符串或者字符串的其中一部分执行操做
对整数和浮点数执行自增或者自减操做
作简单的键值对缓存
LIST 列表 从两端压入或者弹出元素
对单个或者多个元素进行修剪,
只保留一个范围内的元素
存储一些列表型的数据结构,相似粉丝列表、文章的评论列表之类的数据
SET 无序集合 添加、获取、移除单个元素
检查一个元素是否存在于集合中
计算交集、并集、差集
从集合里面随机获取元素
交集、并集、差集的操做,好比交集,能够把两我的的粉丝列表整一个交集
HASH 包含键值对的无序散列表 添加、获取、移除单个键值对
获取全部键值对
检查某个键是否存在
结构化的数据,好比一个对象
ZSET 有序集合 添加、获取、删除元素
根据分值范围或者成员来获取元素
计算一个键的排名
去重但能够排序,如获取排名前几名的用户

Redis的应用场景

总结一

计数器

能够对 String 进行自增自减运算,从而实现计数器功能。Redis 这种内存型数据库的读写性能很是高,很适合存储频繁读写的计数量。

缓存

将热点数据放到内存中,设置内存的最大使用量以及淘汰策略来保证缓存的命中率。

会话缓存

可使用 Redis 来统一存储多台应用服务器的会话信息。当应用服务器再也不存储用户的会话信息,也就再也不具备状态,一个用户能够请求任意一个应用服务器,从而更容易实现高可用性以及可伸缩性。

全页缓存(FPC)

除基本的会话token以外,Redis还提供很简便的FPC平台。以Magento为例,Magento提供一个插件来使用Redis做为全页缓存后端。此外,对WordPress的用户来讲,Pantheon有一个很是好的插件 wp-redis,这个插件能帮助你以最快速度加载你曾浏览过的页面。

查找表

例如 DNS 记录就很适合使用 Redis 进行存储。查找表和缓存相似,也是利用了 Redis 快速的查找特性。可是查找表的内容不能失效,而缓存的内容能够失效,由于缓存不做为可靠的数据来源。

消息队列(发布/订阅功能)

List 是一个双向链表,能够经过 lpush 和 rpop 写入和读取消息。不过最好使用 Kafka、RabbitMQ 等消息中间件。

分布式锁实现

在分布式场景下,没法使用单机环境下的锁来对多个节点上的进程进行同步。可使用 Redis 自带的 SETNX 命令实现分布式锁,除此以外,还可使用官方提供的 RedLock 分布式锁实现。

其它

Set 能够实现交集、并集等操做,从而实现共同好友等功能。ZSet 能够实现有序性操做,从而实现排行榜等功能。

总结二

Redis相比其余缓存,有一个很是大的优点,就是支持多种数据类型。

数据类型说明string字符串,最简单的k-v存储hashhash格式,value为field和value,适合ID-Detail这样的场景。list简单的list,顺序列表,支持首位或者末尾插入数据set无序list,查找速度快,适合交集、并集、差集处理sorted set有序的set

其实,经过上面的数据类型的特性,基本就能想到合适的应用场景了。

string——适合最简单的k-v存储,相似于memcached的存储结构,短信验证码,配置信息等,就用这种类型来存储。

hash——通常key为ID或者惟一标示,value对应的就是详情了。如商品详情,我的信息详情,新闻详情等。

list——由于list是有序的,比较适合存储一些有序且数据相对固定的数据。如省市区表、字典表等。由于list是有序的,适合根据写入的时间来排序,如:最新的***,消息队列等。

set——能够简单的理解为ID-List的模式,如微博中一我的有哪些好友,set最牛的地方在于,能够对两个set提供交集、并集、差集操做。例如:查找两我的共同的好友等。

Sorted Set——是set的加强版本,增长了一个score参数,自动会根据score的值进行排序。比较适合相似于top 10等不根据插入的时间来排序的数据。

如上所述,虽然Redis不像关系数据库那么复杂的数据结构,可是,也能适合不少场景,比通常的缓存数据结构要多。了解每种数据结构适合的业务场景,不只有利于提高开发效率,也能有效利用Redis的性能。



来源:https://blog.csdn.net/ThinkWon/article/details/103522351


- END -
本人的专栏已上线,欢迎订阅

有收获就点个「在看」吧 

本文分享自微信公众号 - 老蒙大数据(simon_bigdata)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。

相关文章
相关标签/搜索