Redis需要知道的一些知识点

Redis为什么快

  1. 完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1);
  2. 数据结构简单,对数据操作也简单,Redis中的数据结构是专门进行设计的;
  3. 采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;
  4. 使用多路I/O复用模型,非阻塞IO
  5. 使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求;

注意第三条

  • 版本3.x ,最早版本,也就是大家口口相传的redis是单线程。
  • 版本4.x,严格意义来说也不是单线程,而是负责处理客户端请求的线程是单线程,但是开始加了点多线程的东西(异步删除)。
  • 最新版本的6.0.x后,告别了单线程,用一种全新的多线程来解决问题。

Redis 4.0之前采用单线程的原因

  1. 使用单线程模型是 Redis 的开发和维护更简单,因为单线程模型方便开发和调试
  2. 即使使用单线程模型也并发的处理多客户端的请求,主要使用的是多路复用和非阻塞 IO;
  3. 对于 Redis 系统来说,主要的性能瓶颈是内存或者网络带宽而并非 CPU。

Redis 逐渐加入了多线程的原因

  1. 单线程下,耗时操作(bigkey的删除)会造成Redis卡顿
  2. 引入惰性删除(unlink key),有效避免卡顿问题。从redis主线程剥离让bio子线程来处理,极大地减少主线阻塞时间。从而减少删除导致性能和稳定性问题。在Redis 4.0就引入了多个线程来实现数据的异步惰性删除等功能,但是其处理读写请求的仍然只有一个线程,所以仍然算是狭义上的单线程。
  3. 随着硬件的发展,redis的性能瓶颈不再是内存了,而是网络IO

Redis 6.0线程模型

在Redis6.0中,多线程机制默认是关闭的,设置io-thread-do-reads配置项为yes,表示启动多线程

  1. 网络数据读写、请求协议解析通过多个IO线程的来处理
  2. 对于的命令执行来说,仍然使用主线程操作

数据类型

https://redis.io/docs/data-types/

  • Strings
  • Lists
  • Sets
  • Hashes
  • Sorted sets
  • Stream
  • Geospatial
  • HyperLogLog
  • Bitmaps
  • Bitfields

性能优化

大key问题

热点key

热点key可能带来的问题

  1. 当某一热点 Key 的请求在某一主机上超过该主机网卡上限时,由于流量的过度集中,会导致服务器中其它服务无法进行。

  2. 如果热点过于集中,热点 Key 的缓存过多,超过目前的缓存容量时,就会导致缓存分片服务被打垮现象的产生

  3. 当缓存服务崩溃后,此时再有请求产生,会缓存到后台 DB 上,由于DB 本身性能较弱,在面临大请求时很容易发生请求穿透现象,会进一步导致雪崩现象,严重影响设备的性能。

如何发现热key

  1. 凭借经验,预估哪些key是热key

比如某商品在做秒杀,那这个商品的key就可以判断出是热key。缺点就是并非所有业务都能预估出哪些key是热key。

  1. 在客户端收集

这个方式就是在操作redis之前,加入一行代码进行数据统计。那么这个数据统计的方式有很多种,也可以是给外部的通讯系统发送一个通知信息。缺点就是对客户端代码造成入侵。

  1. 在Proxy层做收集

Proxy可以是Twemproxy或Codis,是统一的入口。可以在Proxy层做收集上报,但是缺点很明显,并非所有的redis集群架构都有proxy

  1. 用redis自带命令
    • monitor命令,该命令可以实时抓取出redis服务器接收到的命令,然后写代码统计出热key是啥。当然,也有现成的分析工具可以给你使用,比如redis-faina。但是该命令在高并发的条件下,有内存增暴增的隐患,还会降低redis的性能。
    • hotkeys参数,redis 4.0.3提供了redis-cli的热点key发现功能,执行redis-cli时加上–hotkeys选项即可。但是该参数在执行的时候,如果key比较多,执行起来比较慢。
  2. 自己抓包评估
    Redis客户端使用TCP协议与服务端进行交互,通信协议采用的是RESP。自己写程序监听端口,按照RESP协议规则解析数据,进行分析。缺点就是开发成本高,维护困难,有丢包可能性。

解决方案

  1. 利用二级缓存,ehcache或者HashMap。在发现热key以后,把热key加载到系统的JVM中
  2. 备份热key
    一个key存在多个redis节点上。可以通过修改key来实现,例如热点key为a,可以改写成a@redis1,a@redis2,a@redis3
    每个节点都缓存一份数据,把压力分散到不同节点上

你可能感兴趣的:(redis,数据库,java)