Redis面试题(4)
认识Redis
- REmote DIctionary Server(Redis) 是一个由 Salvatore Sanfilippo 写的 key-value 存储系统,是跨平台的非关系型数据库。
- Redis 是一个开源的使用 ANSI C 语言编写、遵守 BSD 协议、支持网络、可基于内存、分布式、可选持久性的键值对(Key-Value)存储数据库,并提供多种语言的 API。
Redis的数据类型都有哪些
- 有五种基本数据类型,分别是string、hash、list、有序集合(zset)、集合(set)。在5.0之后增加了一种Stream类型。
- 额外的有GEO、HyperLogLog、BitMap。
Redis使用的场景有哪些
- 数据缓存(用户信息、商品数量、文章阅读数量)
- 消息推送(站点的订阅)
- 队列(削峰、解耦、异步)
- 排行榜(积分排行)
- 社交网络(共同好友、互踩、下拉刷新)
- 计数器(商品库存,站点在线人数、文章阅读、点赞)
- 基数计算
- GEO计算
Redis功能特点都有哪些
- 持久化
- 丰富的数据类型(string、list、hash、set、zset、发布订阅等)
- 高可用方案(哨兵、集群、主从)
- 事务
- 丰富的客户端
- 提供事务
- 消息发布订阅
- Geo
- HyperLogLog
- 事务
- 分布式事务锁
Redis如何实现分布式锁
- Redis可以使用
setnx key value
+expire key expire_time
来实现分布式锁。 - 正常情况下,上面的命令是没有问题的。当Redis出现异常的情况下,很容易出现非原子性操作。
- 非原子性操作指的的setnx命令执行成功,但是expire没有执行成功,此时key就成为了一个无过期时间的key,一直保留在Redis中,导致其他的请求就无法执行。
- 要解决该问题,可以使用lua脚本实现。通过lua实现命令的原子性操作。
在Redis中使用set命令,加参数也可以实现分布式锁。
set key vale nx ex|px ttl
通过数组定义
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | --- getLock key local key = KEYS[1] local requestId = KEYS[2] local ttl = tonumber(KEYS[3]) local result = redis.call('setnx', key, requestId) if result == 1 then --PEXPIRE:以毫秒的形式指定过期时间 redis.call('pexpire', key, ttl) else result = -1; -- 如果value相同,则认为是同一个线程的请求,则认为重入锁 local value = redis.call('get', key) if (value == requestId) then result = 1; redis.call('pexpire', key, ttl) end end -- 如果获取锁成功,则返回 1 return result |
通过数组定义
1 2 3 4 5 6 7 8 9 | -- releaseLock key local key = KEYS[1] local requestId = KEYS[2] local value = redis.call('get', key) if value == requestId then redis.call('del', key); return 1; end return -1 |
tips:如果对一个key第一次set添加了过期时间,第二次操作时没有添加过期时间,此时key是没有过期时间的(过期时间被覆盖为永久不过期)。
Redis底层数据结构有哪些
Redis底层数据结构主要有六种,这六种构成了五种常用的数据类型。其他的数据类型,例如bitmap、hyperLogLog也是基于这五大数据类型实现。具体的数据结构图如下: