1、为什么要使用缓存?
出于性能和并发的要求
我们在碰到需要执行耗时特别久,且结果不频繁变动的SQL,就特别适合将运行结果放入缓存。这样,后面的请求就去缓存中读取,使得请求能够迅速响应。
在大并发的情况下,所有的请求直接访问数据库,数据库会出现连接异常。这个时候,就需要使用redis做一个缓冲操作,让请求先访问到redis,而不是直接访问数据库。
MySQL执行SQL的并发一般是1500QPS左右,而使用高效的缓存的话,Redis可以达到10W+的QPS。
2、讲一讲常用的缓存数据库(不限于Redis)?
Redis 1、特点:
Redis 是一个基于内存的高性能键值存储系统(基于C编写)
它支持多种数据结构,包括字符串、哈希、列表、集合和有序集合。支持数据持久化、支持分布式、支持事务等。 2、适用场景:
做缓存、实现消息队列、实现计数器、实现业务排行榜等。
MongoDB
1、特点:
MongoDB 是一个文档型数据库(BSON,JSON的拓展)
MongoDB的数据设计跟关系型数据库很类似(可以进行对应)。还支持类似于SQL的复杂查询。
2、适用场景: 内容管理系统(MongoDB的灵活数据模型使其非常适合存储和管理各种类型的内容,如文章、图片、视频等)
实时分析和大数据处理(MongoDB支持复杂查询和聚合操作,它可以存储和处理大规模的日志数据、用户行为数据,然后进行实时数据分析以及大数据处理)
物联网应用(MongoDB的可扩展性和高性能使其适合存储和处理物联网设备生成的大量数据。它可以存储传感器数据、设备状态数据,并支持实时查询和分析)
Memcache 1、特点:
Memcache 是一个基于内存的高速缓存系统,它可以缓存任何类型的数据,包括文本、图像和视频等。
2、适用场景:
Memcache 适用于需要高速读写的场景,比如网站页面缓存、会话管理、数据库查询缓存等。
Ehcache
1、特点:
Ehcache 是一个基于 Java 的缓存系统(JVM缓存),它可以缓存 Java 对象,支持多种缓存策略,包括 LRU、LFU 和 FIFO 等。
EhCache3.x版本中不但提供了堆内缓存heap,还提供了堆外缓存off-heap,并且还提供了数据的持久化操作,可以将数据落到磁盘中disk
2、适用场景:
单体项目中想把缓存的性能提升的比Redis还要快,就可以选择Ehcache(JVM缓存)
Ehcache 适用于需要高速读写的 Java 应用程序,比如 Web 应用程序、企业应用程序等。
3、讲一讲Redis的数据类型,以及每种数据类型的使用场景
1、String
Value可以是String也可以是数字,一般用来做复杂的计数功能的缓存,比如实现计数器的限流算法。就可以使用Redis的String类型来存储计数。同时String还可以使用存储比较简单的缓存数据。
2、Hash
hash 这里value存放的是结构化的对象,比较方便的就是操作其中的某个字段。
比如做单点登录的时候,就可以使用Hash这种数据结构存储用户信息,以cookieId作为key,设置30分钟为缓存过期时间,value中就可以存储各种session的值。
3、List
使用List的数据结构,可以做简单的消息队列的功能。另外还有一个就是,可以利用lrange命令,做基于redis的分页功能,性能极佳,用户体验好。
4、Set
因为set堆放的是一堆不重复值的集合。所以可以做全局去重的功能。
同时Redis提供了交集、并集、差集等操作,可以计算共同喜好,全部的喜好,自己独有的喜好等功能。所以Set可以用来存储用户的标签、爱好之类的。
(为什么不用JVM自带的Set进行去重?因为Redis是支持分布式、集群的,JVM的Set只能实现单体内部的去重,做不了分布式/集群下的去重)
5、sorted set(Zset)
sorted set多了一个权重参数score,集合中的元素能够按score进行排列。可以做排行榜应用,取TOP N操作。
同样还可以实现范围查找的功能。
4、pipeline有什么好处,为什么要用 pipeline?
前面我们已经说过,Redis客户端执行一条命令分为如下4个部分:1)发送命令2)命令排队3)命令执行4)返回结果。
其中1和4花费的时间称为Round Trip Time (RTT,往返时间),也就是数据在网络上传输的时间。
Redis提供了批量操作命令(例如mget、mset等),有效地节约RTT。
但大部分命令是不支持批量操作的,例如要执行n次 hgetall命令,并没有mhgetall命令存在,需要消耗n次RTT。
举例:Redis的客户端和服务端可能部署在不同的机器上。例如客户端在本地,Redis服务器在阿里云的广州,两地直线距离约为800公里,那么1次RTT时间=800 x2/ ( 300000×2/3 ) =8毫秒,(光在真空中传输速度为每秒30万公里,这里假设光纤为光速的2/3 )。而Redis命令真正执行的时间通常在微秒(1000微妙=1毫秒)级别,所以才会有Redis 性能瓶颈是网络这样的说法。
Pipeline(流水线)机制能改善上面这类问题,它能将一组 Redis命令进行组装,通过一次RTT传输给Redis,再将这组Redis命令的执行结果按顺序返回给客户端,没有使用Pipeline执行了n条命令,整个过程需要n次RTT。
使用Pipeline 执行了n次命令,整个过程需要1次RTT。
Pipeline并不是什么新的技术或机制,很多技术上都使用过。而且RTT在不同网络环境下会有不同,例如同机房和同机器会比较快,跨机房跨地区会比较慢。
redis-cli的--pipe选项实际上就是使用Pipeline机制,但绝对部分情况下,我们使用Java语言的Redis客户端中的Pipeline会更多一点。
代码参见:
com.msb.redis.adv.RedisPipeline
总的来说,在不同网络环境下非Pipeline和Pipeline执行10000次set操作的效果,在执行时间上的比对如下:
差距有100多倍,可以得到如下两个结论:
1、Pipeline执行速度一般比逐条执行要快。
2、客户端和服务端的网络延时越大,Pipeline的效果越明显。
Pipeline虽然好用,但是每次Pipeline组装的命令个数不能没有节制,否则一次组装Pipeline数据量过大,一方面会增加客户端的等待时间,另一方面会造成一定的网络阻塞,可以将一次包含大量命令的Pipeline拆分成多次较小的Pipeline来完成,比如可以将Pipeline的总发送大小控制在内核输入输出缓冲区大小之内或者控制在单个TCP 报文最大值1460字节之内。
内核的输入输出缓冲区大小一般是4K-8K,不同操作系统会不同(当然也可以配置修改)
最大传输单元(Maximum Transmission Unit,MTU),这个在以太网中最大值是1500字节。那为什么单个TCP 报文最大值是1460,因为因为还要扣减20个字节的IP头和20个字节的TCP头,所以是1460。
同时Pipeline只能操作一个Redis实例,但是即使在分布式Redis场景中,也可以作为批量操作的重要优化手段。
5、Redis官方为什么不提供 Windows版本?
因为Redis的linux的版本本身就比较完善,一般的服务器都是部署在Linux上,所以没有官方版本,而大家看到的windows版本是微软的开发者爱好者仿照Linux的Redis版本写的一个而已。(不能作为生产的实践)
6、说说你对Redis事务的理解!
大家应该对事务比较了解,简单地说,事务表示一组动作,要么全部执行,要么全部不执行。
例如在社交网站上用户A关注了用户B,那么需要在用户A的关注表中加入用户B,并且在用户B的粉丝表中添加用户A,这两个行为要么全部执行,要么全部不执行,否则会出现数据不一致的情况。
Redis提供了简单的事务功能,将一组需要一起执行的命令放到multi和exec两个命令之间。multi 命令代表事务开始,exec命令代表事务结束。另外discard命令是回滚。
一个客户端
另外一个客户端
在事务没有提交的时查询(查不到数据)
在事务提交后查询(可以查到数据)
可以看到sadd命令此时的返回结果是QUEUED,代表命令并没有真正执行,而是暂时保存在Redis中的一个缓存队列(所以discard也只是丢弃这个缓存队列中的未执行命令,并不会回滚已经操作过的数据,这一点要和关系型数据库的Rollback操作区分开)。
只有当exec执行后,用户A关注用户B的行为才算完成,如下所示exec返回的两个结果对应sadd命令。
但是要注意Redis的事务功能很弱。在事务回滚机制上,Redis只能对基本的语法错误进行判断。
如果事务中的命令出现错误,Redis 的处理机制也不尽相同。
1、语法命令错误
例如下面操作错将set写成了sett,属于语法错误,会造成整个事务无法执行,事务内的操作都没有执行:
2、运行时错误
例如:事务内第一个命令简单的设置一个string类型,第二个对这个key进行sadd命令,这种就是运行时命令错误,因为语法是正确的:
可以看到Redis并不支持回滚功能,第一个set命令已经执行成功,开发人员需要自己修复这类问题。
Redis的事务原理
事务是Redis实现在服务器端的行为,用户执行MULTI命令时,服务器会将对应这个用户的客户端对象设置为一个特殊的状态,在这个状态下后续用户执行的查询命令不会被真的执行,而是被服务器缓存起来,直到用户执行EXEC命令为止,服务器会将这个用户对应的客户端对象中缓存的命令按照提交的顺序依次执行。
7、Redis 有哪些高级功能?说一说!
消息队列。
自动过期删除
分布式锁
附近的人--GEO的数据类型
慢查询分析
Bitmaps二进制数组
布隆过滤器解决缓存击穿问题