Redis数据库知识点总结

969 阅读7分钟

Redis数据库常见问题

Redis是单线程的,在一个瞬间只会执行一个命令,命令只能一个一个的执行

1.Redis单线程为什么会这么快?

  • 纯内存,本质是数据放在内存中,速度非常快
  • 非阻塞IO
  • 避免线程切换和竞态消耗

2.Redis有哪些数据类型?

  • String:不仅可以是字符串,还可以是整数、浮点数类型 -常见使用场景

    • 缓存:作为各种信息的缓存使用
    • 计数器:天然适合做计数器,因为是单线程的,所以在并发执行计数增加时不会出错
    • 分布式锁
  • List:一个链表,链表上的每个节点都包含了一个字符串

    • 双向链表实现
    • 可以重复、两头插入弹出、有序
    • 常见使用场景:关注列表,消息列表
  • Hash:String类型的field和value的映射表

    • 适合存储对象
    • 常见使用场景:购物车
  • Set:集合

    • 无序,无重复元素
    • 提供了判断某个元素是否在set中的接口,基于set可以实现并集、交集、差集
    • 常见使用场景:共同关注、共同粉丝之类的功能
  • sorted set:有序集合

    • 和set相比,Zset增加了一个权重参数score,使得集合中的元素能够按照score有序排列

    • 常见使用场景:排行榜

3.Sorted set底层实现

跳跃表:基于多指针有序链表实现的 与红黑树相比优点:

  • 插入速度非常快,因为不需要旋转操作来维持平衡
  • 更好实现
  • 支持无锁操作

4.redis中什么是一致性hash?是为了解决什么问题?

在使用Redis集群的时候,会使用hash的方式来定位服务器,即通过对服务器数量取模的方式来进行hash 这样的方式会带来一个问题,那就是在服务器数量变动的时候,原本所有的缓存的位置都要发生改变

一致性Hash算法: 一致性hash算法也是通过取模的方式,不过不是对服务器数量取模,而是对2^32取模

简单的来说,一致性Hash算法将哈希值空间组成了一个虚拟的圆环(hash环),整个空间按照顺时针组织,从0开始,一直到2^32-1,然后对每个服务器使用hash确定其在圆环上的位置,当需要确定数据在哪台服务器上时,就是用同样的函数进行hash找到在圆环上的位置,从这个位置开始,顺时针遇到的第一台服务器就是数据存放的地方。这样的话当服务器数量增加或者减少,受影响的数据会少很多。比如当服务器数量新增一台,那么受影响的数据仅仅是这台新服务器到其前一台服务器(逆时针方向的前一台)之间的数据会受到影响,其他的数据不会受到影响;当某一台服务器出现故障时,那么受影响的数据仅仅是这台服务器和前一台服务器之间的数据

5.redis和memecached区别?

两者都是非关系型内存键值数据库,两者主要有以下不同:

  • 数据类型:Memcached仅支持字符串类型,而redis支持五种数据类型
  • 数据持久化:Memcached不支持持久化,Redis有RDB快照和AOF日志两种持久化方式
  • 分布式:Memcached不支持分布式
  • 内存管理机制:
    • 在Redis中并不是所有的数据都会一直存储在内存中,一些很久不被使用的数据会被交换的磁盘当中存储,而Memcached所有的数据会一直在内存中
    • Memcached的内存使用率不高,将内存分成特定长度的块来存储数据,但是会导致内存利用不足的问题

6.Redis的持久化机制?

Redis的持久化方式有两种:RDB方式和AOF方式

  • RDB(Redis DataBase快照):即快照方式,redis可以通过创建快照来获得存储在内存中数据在某个时间点的副本,redis创建快照之后,还可以对快照进行备份,可以将快照复制到其他服务器用以创建相同数据的服务器副本,或者重启服务器以后恢复数据。RDB是Redis默认的持久化方式
  • AOF(Append-only File):AOF持久化会将被执行的写命令写入AOF文件的末尾,记录数据的变化

7.事务的特性有哪些,redis的事务实现了哪些呢?

事物的特性:ACID,即原子性,一致性,隔离性,持久性

在Redis中,事务总是具有原子性,一致性和隔离性,当Redis运行在特定的模式下(开启持久化),事务也具有持久化

8.什么是缓存穿透和缓存雪崩?有什么解决方案?

缓存雪崩:缓存同一时间大面积的失效,造成数据库在短时间内承受大量请求而崩掉

缓存穿透:一般是黑客故意去请求缓存中不存在的数据,导致所有的请求都落在数据库上,造成数据库在短时间内承受大量的请求而崩掉

缓存雪崩的解决方案

  • 事前:尽量保证整个redis集群的高可用性,发现机器宕机尽快补上。选择合适的内存淘汰策略
  • 事中:本地ehcache缓存+hystrix限流加降级,避免MySql崩掉
  • 事后:利用redis持久化机制尽快恢复缓存

缓存穿透的解决方案

  • 布隆过滤器:将所有可能存在的数据hash到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对底层存储系统的查询压力
  • 如果一个查询的返回为空,仍然把这个空结果缓存,但是过期时间会设置的很短,最长不超过5分钟

9.Redis怎么设置过期时间

expire key seconds,比如:

expire xiaoming 30,设置xiaoming这个key的过期时间为30s,可以使用ttl key来查看这个key的剩余存活时间

ttl xiaoming 19,xiaoming这个key的剩余存活时间为19s

  • expire key ttl seconds,设置过期时间为ttl秒
  • pexpire key ttl milliseconds,设置过期时间为ttl毫秒
  • expireat key ttl timestamp,设置过期时间为ttl所代表的秒数的时间戳
  • pexpireat key ttl timestamp,设置过期时间为ttl所代表的毫秒数时间戳

10.怎么保证缓存和数据库的双写一致

  • 给缓存设置过期时间,所有的写操作以数据库为准,只要达到缓存过期时间,后续对数据库的读操作自然会读取新值回填缓存

  • 先更新数据库,再删除缓存:也就是Cache Aside Pattern,读的时候先读缓存,缓存中没有就去数据库中读,然后更新缓存;写的时候先更新数据库,再删除缓存。

    可以采用异步更新缓存(基于订阅binlog的同步机制):

    • 一旦mysql中产生了写入、删除或者更新等操作,就可以把binlog相关的消息推送到redis,redis再根据binlog中的记录来更新redis

11.Redis内存淘汰机制

当redis存储超过了maxmemory时,就需要对Redis进行内存淘汰,主要策略有:

  • volatile-lru:从已设置过期时间的数据集中淘汰最近最久未使用的数据
  • volatile-ttl:从已设置过期时间的数据集中淘汰将要过期的数据
  • volatile-random:从已设置过期时间的数据集中选择任意数据淘汰
  • allkeys-lru:从数据集中淘汰最近最久未使用的数据
  • allkeys-random:从数据集中选择任意数据淘汰
  • noeviction:不淘汰数据,当超出内存的时候报错