PHP面试宝典之Redis上篇

setex、set、setnx的区别?

setex:给key指定value值,重写旧值,并同时设置过期时间,单位秒;

set:设置value值

setnx:判断有没有key,如果有则返回失败,如果没有则继续赋值

expire:设置key的过期时间,单位秒

connect和pconnect的区别?

connect:脚本结束之后连接就释放了

pconnect:脚本结束之后连接不释放,连接保持在php-fpm进程中
所以使用pconnect代替connect,可以减少频繁建立redis连接的消耗。

Redis设置密码:config set requirepass 123456

Redis授权密码:auth 123456

redis和memcached的区别?

1:数据类型:memcache仅支持简单k-v;redis支持string、list、set、zset等

2:端口号:redis:6379;memcache:11211;

3:数据安全:redis断电数据不丢失;memcache重启数据清空

4:数据持久化:redis数据可恢复;memcache不可恢复

5:性能方面:小数据存储redis性能更高,100k以上数据,memcached性能更高

6:redis单核,memcache多核

7:k-v情况下,memcache内存使用率更高,hash时redis更高

redis数据类型及使用场景?

string:字符串;缓存json对象,简单计数:访问次数、点赞、转发量

list:列表;消息队列、发红包

hash:哈希;购物车

set:无序集合;黑名单过滤、共同关注、抽奖

zset:有序集合;热搜排行榜

redis各类型常用命令?

  • 字符串:

    set key value:设置key的值

    get key:获取key的值

    setex key seconds value:设置key的有效时长秒,以及value值

    setnx key value:设置key的值,如果不存在就设置,存在就返回错误

  • hash哈希:objectName:对象名或用户ID,name:字段名,value:字段值

    hset objectName name value:给指定对象的,name字段设置value值

    hget objectName name:获取指定对象的,name字段的值

    hdel objectName name:删除指定对象的,name字段

    hvals objectName:获取指定对象中的,所有字段的值

    hgetall objectName:获取指定对象中的,所有字段,名和值

  • list列表:字符串列表,按插入顺序排序

    lpush listName value1 [value2]:将一个或多个值插入到列表头部

    lrange listName start stop:获取列表指定范围内的元素

    rpop listName:移除并获取列表最后一个元素

    llen listName:获取列表的长度

  • set无序集合:无序,成员不重复

    sadd setName member1 member2…:向集合中添加一个或多个成员

    smembers setName:返回集合中所有成员,无序的,和插入顺序无关

    scard setName:获取集合成员数

    sinter setName1 setName2:返回集合交集

    sunion setName1 setName2:返回集合并集(集合中所有成员,相同成员只显示一次)

    sdiff setName1 setName2:返回集合差集(前集合有,后集合没有的)

    srem setName member1:移除集合中的成员(一个或多个)

  • zset有序集合:字符串类型集合,每个成员都关联一个双精度浮点类型的分数作为权重,redis通过权重从小到大排序,成员唯一,但分数可重复

    zadd zsetName score1 member1:向有序集合中添加成员,或更新成员分数(一个或多个)

    zincrby zsetName score member:给指定成员的权重增加指定分数

    zrem zsetName member1:移除集合中成员(一个或多个)

zset底层数据结构?

底层存储结构包括:ziplist或skiplist两种;

zip list:键值对小于128个,每个元素小于64字节

skip list:空间换时间,通过maxlevel提高搜索效率;包含dict(保存key/value)和zskiplist(有序的元素列表)两个数据结构

zset存储过程?

1:首先解析参数,得到元素,及分值

2:查找key对应的,集合是否存在,不存在,创建

3:如果是ziplist,检查元素是否存在,存在,先删除再添加,不存在,添加且检查是否需要转为skiplist对象

4:如果是skiplist,检查元素是否存在,存在,先删除再添加,不存在,直接添加,并同时更新dict对象

redis持久化如何实现?

rdb快照、aof文件追加、混合持久化

rdb:默认持久化方式;将内存按二进制写入磁盘;
快照:全量快照、增量快照;

命令:
save:同步快照,会阻塞;

bgsave:异步快照,不阻塞;

aof文件追加:将相关操作,以日志形式存储到文件末尾

混合持久化:先按rdb方式写入开头,后将操作按aof格式追加存储

rdb和aof的区别?

rdb:以快照方式,将一段时间内的数据写入到磁盘,并使用二进制压缩存储;数据恢复时性能更好,但数据安全性较低,服务器宕机时和最后一次快照之间的数据可能丢失

aof:以日志形式记录操作命令,可以实时持久化,数据安全性比较高,后期文件过大,传输困难

redis优缺点?

优点:

1:读写优异,读11万/秒,写8万1/秒

2:支持数据持久化,支持事务

3:支持字符串、哈希、无序集合、有序集合、列表等数据结构

4:支持主从复制、读写分离

缺点:

1:受物理内存限制

2:不具备自动容错和恢复功能

3:宕机时,若数据未同步,会导致数据丢失

4:在线扩容复杂,需预留空间,造成资源浪费

redis是单线程还是多线程?

在6.0之前,redis的网络处理和键值对,都是单线程,6.0之后把网络处理部分改成了多线程模式,而键值对读写依然还是单线程

为什么redis键值对,读写要使用单线程设计?

如果使用多线程,要考虑线程切换的开销,还要引入锁机制保证线程安全,为了避免这些问题,所以使用单线程

redis为什么会快?

1:单线程

2:基于内存,相比于磁盘读写更快

3:数据结构简单

4:多路i/o复用,提高系统吞吐量,非阻塞i/o

5:自己vm机制,比系统调用函数速度更快

什么是i/o多路复用?

一个或多个线程处理多个tcp连接,无需创建和维护过多的进程/线程

redis过期策略?

定时删除、定期删除、惰性删除

定时删除:设置过期时间时,创建定时器,过期立即删除(对cpu不友好)

定期删除:每隔一段时间,对所有键进行检查,过期立即删除(最佳方案)

惰性删除:每次获取键时,判断是否过期,过期立即删除(浪费内存)

为什么redis的键过期了,却还占用内存?

这是由过期策略来决定的

Redis过期策略是:定期删除+惰性删除

定期删除是每个100毫秒,就随机检查一些key的过期情况,过期就删除。但有可能会有过期的key并未被检查到,也就不会被删除。这时就要靠惰性删除,当查询的时候判断是否过期,过期就删除。但如果没有查询,就会导致有的key明明过期了,但却仍然占用着内存。

如果大量过期的key堆积在内存里未被删除,会导致redis内存耗尽。该如何处理?

走内存淘汰机制

Redis回收进程如何工作?

一个客户端添加了新的数据,Redis检查内存使用情况,超过内存限制,就会根据回收策略进行回收

Redis回收策略,淘汰策略

默认:缓存达到设置临界点,再次写入的请求,将禁止写入,直接响应错误

其他:
1):从设置过期时间的数据集中淘汰最近最少使用的数据

2):从设置过期时间的数据集中随机选择数据淘汰

3):从设置过期时间的数据集中淘汰即将过期的数据

4):从数据集中淘汰最近最少使用的数据

5):从数据集中随机选择数据淘汰

6):禁止驱逐数据,永不回收

删除过期键值是由主线程操作,如果一次性大量删除会造成用户阻塞

MySQL里有2000万数据,Redis只有20万,如何保证Redis里的数据都是热点数据?

当Redis内存中的数据集达到一定的值的时候,就会施行数据淘汰机制,可以设置为淘汰最近最少使用的数据

你可能感兴趣的:(面试宝典,redis,php,面试)