【绝杀面试官七问】Redis【进阶篇】(一)
“ 每天十分钟,轻松拿offer。”
01
—
【问】Redis 中的管道有什么用?
【答】
一次请求/响应服务器能实现处理新的请求即使旧的请求还未被响应。这样就可以将多个命令发送到服务器,而不用等待回复,最后在一个步骤中读取该答复。这就是管道(pipelining),是一种几十年来广泛使用的技术。例如许多POP3协议已经实现支持这个功能,大大加快了从服务器下载新邮件的过程。
02
—
【问】怎么理解 Redis 事务?
【答】
事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。
redis事务 没有隔离级别
03
—
【问】Redis 事务相关的命令有哪几个?
【答】
MULTI EXEC DISCARD WATCH
ps:
MULTI命令
用于开启一个事务,它总是返回OK。MULTI执行之后,客户端可以继续向服务器发送任意多条命令, 这些命令不会立即被执行,而是被放到一个队列中,当 EXEC命令被调用时, 所有队列中的命令才会被执行。
EXEC命令
负责触发并执行事务中的所有命令:
如果客户端成功开启事务后执行EXEC,那么事务中的所有命令都会被执行。
如果客户端在使用MULTI开启了事务后,却因为断线而没有成功执行EXEC,那么事务中的所有命令都不会被执行。
需要特别注意的是:即使事务中有某条/某些命令执行失败了,事务队列中的其他命令仍然会继续执行——Redis不会停止执行事务中的命令,而不会像我们通常使用的关系型数据库一样进行回滚。
DISCARD命令
当执行 DISCARD 命令时, 事务会被放弃, 事务队列会被清空,并且客户端会从事务状态中退出。
WATCH 命令
可以为Redis事务提供 check-and-set (CAS)行为。被WATCH的键会被监视,并会发觉这些键是否被改动过了。如果有至少一个被监视的键在 EXEC 执行之前被修改了, 那么整个事务都会被取消, EXEC 返回nil-reply来表示事务已经失败。
04
—
【问】Redis key 的过期时间和永久有效分别怎么设置?
【答】
通过expire设置过期时间
通过persist对key进行持久化
例如:expire key 100 (key在100秒后过期)
例如:persist key(清楚key的过期时间)
05
—
【问】Redis 如何做内存优化?
【答】
1、缩减键值对象
缩减键(key)和值(value)的长度。
key长度:如在设计键时,在完整描述业务情况下,键值越短越好。
value长度:值对象缩减比较复杂,常见需求是把业务对象序列化成二进制数组放入Redis。首先应该在业务上精简业务对象,去掉不必要的属性避免存储无效数据。其次在序列化工具选择上,应该选择更高效的序列化工具来降低字节数组大小。以JAVA为例,内置的序列化方式无论从速度还是压缩比都不尽如人意,这时可以选择更高效的序列化工具,如: protostuff,kryo等,
2、共享对象池
对象共享池指Redis内部维护[0-9999]的整数对象池。创建大量的整数类型redisObject存在内存开销,每个redisObject内部结构至少占16字节,甚至超过了整数自身空间消耗。所以Redis内存维护一个[0-9999]的整数对象池,用于节约内存。除了整数值对象,其他类型如list,hash,set,zset内部元素也可以使用整数对象池。因此开发中在满足需求的前提下,尽量使用整数对象以节省内存。
3、字符串优化
4、编码优化
5、控制key的数量
06
—
【问】Redis 回收进程如何工作的?
【答】
一个客户端运行了新的命令,添加了新的数据。Redi检查内存使用情况,如果大于maxmemory的限制, 则根据设定好的策略进行回收。一个新的命令被执行,等等。
ps:我们不断地穿越内存限制的边界,通过不断达到边界然后不断地回收回到边界以下。如果一个命令的结果导致大量内存被使用(例如很大的集合的交集保存到一个新的键),不用多久内存限制就会被这个内存使用量超越。
07
—
【问】Redis 加锁机制?
【答】
在事务中,可以通过watch命令来加锁;使用 UNWATCH 可以取消加锁;
如果在事务之前,执行了WATCH(加锁),那么执行 EXEC 命令或 DISCARD 命令后,锁对自动释放,即不需要再执行 UNWATCH 了。Redis采用了乐观锁策略(通过watch操作)。
ps:Redis只支持乐观锁!
乐观锁支持读操作,适用于多读少写的情况!