1.说一下Redis有什么特点?
1)Redis基于k-v数据库,访问速度快
2)支持数据的持久化(可以将数据保存在硬盘,重启Redis之后可以重新写入内存)
3)支持丰富的数据类型,主要包括string、list、hash、set、zset
4)支持主从数据备份
5)支持事务
2.说一下Redis都有什么数据类型?
Redis 有五个常用的数据类型
string ,list,set,zset,和hash
Redis5.0以后添加了新的数据类型stream
3.说一下Redis常有的命令
Redis的命令非常多
string类型
- set:赋值;
- get:获取指定key的值;
- setnx:当设置的key不存在时则进行设置;
- setex:设置key的有效时间;
- mset:一次为多个key赋值;
- mget:一次获取多个key的值;
- incr:对key的值做加加操作,并返回新的值;
hash类型
- hset:赋值;
- hget:获取某个key下的某个field的值;
- hgetall:获取一个key下所有field和value;
- hkeys:获取所有的key;
- hvals:获取某个key下所有的value;
- hexists:测试给定key下的field是否存在;
list类型
- lpush:从头部(链表左侧)添加元素;
- lpop:从list头部获取元素
- rpush:从尾部(链表右侧)添加元素;
- rpop:从list尾部获取元素
- lrange:查看list的所有元素:lrange list名称 0 -1
- linsert:在某个元素的前后插入元素 linsert list before/after 原有元素 新元素
- lrem:移除元素 lrem list 2(移除个数) “key”
- rpoplpush:从原来的list的尾部删除元素,并将其插入到新的list的头部
- lindex:返回指定索引的值
- llen:返回list的元素个数
set类型
- sadd:添加元素;
- smembers:获取集合中所有元素
- sismember:判断元素是否在集合中
- srem:删除元素
- scard:获取元素个数,相当于count
- spop:随机返回删除的元素
- sdiff:差集,返回在第一个set里面而不在后面任何一个set里面的项(谁在前以谁为标准)
- sdiffstore:差集并保留结果
- sinter:交集,返回多个set里面都有的项
- sinterstore:交集并保留结果
- sunion:并集
- sunionstore:并集并保留结果
- smove:移动元素到另一个集合
zset类型
- zadd:添加元素;
- zrange:获取索引区间内的元素;
- zrangebyscore:获取分数区间内的元素
4.说一下Redis和MemCache的区别
1.在存储方式方面
Memecache 把数据全部存在内存中,不能持久化数据
Redis支持数据的持久化(RDB和AOF)
2.在数据类型方面
Redis在数据类型上的支持 比memecache多的多
3.在底层模型方面
redis在2.0版本后增加了自己的VM特性,突破物理内存的限制
Memcache可以修改最大可用内存,采用LRU算法
4.数据一致性方面
Memcache在并发场景下,用CAS保证一致性;
Redis 事务支持比较弱,只能保证事务中的每个操作连续执行
附:Memcache的介绍
1. Memcached的优点:
- Memcached可以利用多核优势,单实例吞吐量极高,可以达到几十万QPS(取决于key、value的字节大小以及服务器硬件性能,日常环境中QPS高峰大约在4-6w左右)。
2. Memcached的局限性:
只支持简单的key/value数据结构,不像Redis可以支持丰富的数据类型。
无法进行持久化,数据不能备份,只能用于缓存使用,且重启后数据全部丢失。
无法进行数据同步,不能将Memcached中的数据迁移到其他Memcached实例中。
Memcached内存分配采用Slab Allocation机制管理内存,value大小分布差异较大时会造成内存利用率降低,并引发低利用率时依然出现踢出等问题。
- 需要用户注重value设计
5.关于Redis的回收策略,过期机制的相关问题
Redis 回收策略过期机制? Redis内存满了怎么办,有什么替换策略?
问题2:假如我有10亿条数据,可以拿30%放进redis缓存吗?redis缓存有没有限制?
问题3:MySQL有1000万数据,Redis只存20w的数据,如何保证redis中的数据都是热点数据?
回答:
Redis 内存数据集上升到一定大小的时候,会实行数据淘汰策略
Redis key过期的方式有三种
1.被动删除:当读、写一个已经过期的key时,会触发惰性删除策略,直接删除掉过期的key
2.主动删除:由于惰性删除策略无法保证冷数据被及时删掉,所以Redis会定期主动淘汰一批已过期的key
3.当前已用内存超过maxmemory时,触发主动清理策略
当前已用内存超过maxmemory限定时,触发主动清理策略,主动清理策略有6种:
1. volitile-lru:从已设置过期时间的数据集中挑选"最近最少使用"的数据进行淘汰;
2. volitile-ttl:从已设置过期时间的数据集中挑选"将要过期"的数据进行淘汰;
3. volitile-random:从已设置过期时间的数据集中"任意"挑选数据进行淘汰;
4.allkeys-lru:从数据集中挑选"最近最少使用"的数据进行淘汰
5. allkeys-random:从数据集中"任意"选择数据进行淘汰;
6. no-envicition:设置永不过期,禁止驱逐数据;
Redis缓存怎么与数据库数据保持一致? (缓存与数据双写一致)
一、什么是缓存与数据库双写一致问题?
如果仅仅查询的话,缓存的数据和数据库的数据是没问题的。
但是,当我们要更新时候呢?各种情况很可能就造成数据库和缓存的数据不一致了。
比如:数据库中存储的某篇文章的点赞数为10,而Redis中存储的点赞数为11;
二、对于读操作
- 如果数据在Redis缓存里,那么就直接取Redis缓存的数据。
- 如果数据不在Redis缓存里,那么先去查询数据库,然后将数据库查出来的数据写到Redis缓存中。
- 最后将数据返回
从理论上说,只要我们设置了键的过期时间,我们就能保证缓存和数据库的数据最终是一致的。
因为只要缓存数据过期了,就会被删除。之后再读的时候,如果缓存里没有,可以查数据库的数据,然后将查出来的数据写入到缓存中。
除了设置过期时间,我们还需要做更多的措施来尽量避免数据库与缓存处于不一致的情况发生。
这个时候,跟面试官说一下几种处理策略:
- 先更新数据库,再删除缓存
这种策略会出现如下情况
情形1. 如果更新数据库就失败了,程序可以直接返回错误(Exception),不会出现数据不一致。
情形2. 更新数据库成功,删除缓存失败;这就会导致数据库里是新数据,而缓存里是旧数据。
解决情形2思路:
1.先删除缓存,再更新数据库。如果数据库更新失败了,那么数据库中是旧数据,缓存中是空的,那么数据不会不一致。
这样读的时候缓存没有,所以去读了数据库中的旧数据,然后更新到缓存中。
2. 将需要删除的key发送到消息队列中,自己消费消息,获得需要删除的key,不断重试删除操作,直到成功
- 先删除缓存,再更新数据库
这种策略会出现如下美好情况
1. 删除缓存成功,更新数据库失败,这样的话,数据库和缓存的数据最终是一致的。
2. 删除缓存失败了,我们可以直接返回错误(Exception),数据库和缓存的数据还是一致的。
但是在并发场景下,就会下面的问题:
- 线程1删除了缓存;
- 线程2查询,发现缓存已不存在;
- 线程2去数据库查询得到旧值;
- 线程2将旧值写入缓存;
- 线程1将新值写入数据库;
- 所以也会导致数据库和缓存不一致的问题;
解决思路:
将删除缓存、修改数据库、读取缓存等的操作积压到队列里边,实现串行化。
Redis负载均衡了解吗?怎么实现的?
利用Redis官方提供的Redis集群方案实现Redis数据的负载均衡
Redis集群自动分割数据到不同的节点上,整个集群的部分节点失败或者不可达的情况下能够继续处理命令、
Redis集群引入了哈希槽的概念,集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽,集群的每个节点负责一部分hash槽。
你们Redis做读写分离了么
不做读写分离,我们用的是Redis集群架构,是属于分片集群的架构;
Redis本身在内存上操作,不会涉及IO吞吐,即使读写分离也不会提升太多性能;
Redis在生产上的主要问题是考虑容量,单机最多10-20G,key太多降低Redis性能,因此采用分用分片集群结构,已经能保证了我们的性能
如果使用了读写分离后,还要考虑主从一致性,主从延迟等问题,会增加务复杂度。
Redis集群机制中,你觉得有什么不足的地方
1、默认不支持批量操作,如不支持mset、mget等命令
2、如果一个key对应的value是Hash类型的,若Hash对象非常大,是不支持映射到不同节点的,只能映射到集群中的一个节点上!
了解Redis的多数据库机制吗? 了解多少?
1.单机下的Redis默认支持16个数据库;但是
-不支持自定义数据库名称
-不支持为每个数据库设置访问密码
-数据库之间不是完全隔离的,FLUSHALL命令会清空所有数据库的数据
-多数据库不适用存储不同的应用数据
2.我们生产环境中使用Redis集群,集群架构下只有一个数据库空间,即db0
因此,我们没有使用Redis的多数据库功能!
6.10 说一下Redis事务?
1. Redis对事务的支持比较简单,它是一组命令的集合,命令被依次顺序的执行;
2. 我们在生产上采用的是Redis集群,不同的key是可能分到不同的Redis节点上的,在这种情况下Redis的事务机制是不生效的;
3. Redis事务不支持回滚操作,所以基本没有使用过;
Redis持久化的两种方式及应用场景?
两种方式RDB和AOF
RDB是在不同的时间点,将Redis某一时刻的数据生成快照,并保存在磁盘上
AOF是只允许追加不允许改写文件,是将Redis执行过的所有写指令记录下来,在下次redis重启的时候,只要把这些指令从前到后重复执行一遍,就可以实现数据恢复
RDB持久化触发方式:自动触发和手动触发
自动触发方式在redis.conf文件配置
手动触发方式: save命令:执行此命令会阻塞Redis服务器
bgsave命令:执行该命令时,Redis会在后台异步进行快照操作
AOF持久化
默认的AOF持久化策略是每秒钟一次同步策略
AOF的同步策略还有always和no两种,加上everysec,共三种
RDB可以和AOF同时使用吗?
RDB和AOF两种方式可以同时使用,这时如果Redis重启则会优先采用AOF方式进行数据恢复因为AOF方式的数据恢复完整度更高;