话不多少 先上图
Redis支持的五大数据类型包括 String(字符串 用法: 键 值), Hash(哈希 类似Java中的 map 用法: 键 键值对), List(列表 用法:键 集合 不可以重复), Set(集合 用法:键 集合 可以重复), Zset(sorted set 有序集合 用法: 键 值 值)
单线程,多线程
在一开始的时候,Redis采用的是单线程模型,因为Redis是一个基于内存的数据库,将所有的数据放入内存,所以使用单线程的操作效率是最高的, 多线程会上下文切换消耗大量时间,对于内存系统来说,单线程才能产生更高的效率。但是单线程不意味着整个Redis就一个线程,Redis其他模块还有各自的线程
Redis基于内存操作,CPU并不是性能瓶颈,Redis的瓶颈是根据机器的内存和网络带宽。在6.0的版本中引入了多线程。
这个I/O threads 指的是网络I/O处理方面使用了多线程,如网络数据的读写和协议解析等,这是因为读写网络的read/write在Redis执行期间占用了大部分CPU时间,如果把这部分模块使用多线程方式实现会对性能带来极大地提升。但是Redis执行命令的核心模块还是单线程的。
目前最新的6.0版本中,I/O多线程处理模式需要在配置文件中开启。
单线程为什么快
1. 纯内存操作
2. 单线程操作避免了上下文的切换
3. 采用了非阻塞i/o多路复用机制
Redis大部分操作在内存完成
采用IO多路复用机制
非CPU密集型任务
单线程的优势
Redis大部分操作在内存完成
采用了非阻塞i/o多路复用机制
单线程操作避免了上下文切换导致的性能损耗
避免多线程上下文切换导致的性能损耗
避免多线程访问共享资源加锁导致的性能损耗
所以Redis正是基于有以上这些优点,所以采用了单线程模型来完成请求处理的工作。
雪崩,穿透,击穿
一、缓存穿透
1.问题描述:
在查询一个一定不存在的数据时,由于数据库中没有,不会缓存到redis中,所以缓存百分百不会命中,将去数据库中查询,数据库也没有此记录,循环往复,每次查询缓存无法命中,对数据库(数据存储层)造成压力,失去了缓存的意义。
2.风险:
利用数据库中不存在的数据,进行恶意攻击,数据库瞬时压力增大,导致数据库崩溃。
3.解决办法:
将查询到的null结果也缓存到redis中,并加入短暂的过期时间
最常见的则是采用布隆过滤器,将所有可能存在的数据哈 希到一个足够大的 bitmap 中,一个一定不存在的数据会被这个 bitmap 拦截掉,从而避免了对底层存 储系统的查询压力。
二、缓存雪崩
1.问题描述:
缓存雪崩是设置缓存时,设置了相同的过期时间,在大并发量不间断的访问下,缓存在某一时刻全部失效,此时所有的查询压力都会分配到数据库,数据库瞬时压力过大导致雪崩。
2.解决办法:
在原有的失效时间基础上,增加一个1-5分钟随机值,使其缓存时间不一样,减少重复率,减小数据库查询压力,降低了集体缓存失效的概率。
一般并发量不是特别多的时候,使用最多的解决方案是加锁排队。
给每一个缓存数据增加相应的缓存标记,记录缓存的是否失效,如果缓存标记失效,则更新数据缓存。
三、缓存击穿
1.问题描述:
对于热点数据来说,在不间断的大并发量情况下,还设置了过期时间,可能在失效的那一瞬间,被高频访问,此时redis中的缓存已经失效,所有查询压力都会落到数据库上,这种现象就叫做缓存击穿。
2.解决办法:
加锁处理。
思路:大量并发前来查询,只让一个线程去数据库查询,其他线程等待,查到后该线程释放锁,其他人获取锁,在获取到锁后,先查寻redis缓存中是否有数据,如果没有为第一个获取到锁的线程,查询数据库;有数据则直接返回。
减少重复率,减小数据库查询压力,降低了集体缓存失效的概率。
Redis key的淘汰策略有哪些
no evictionno ɪˈvɪkʃn
Redis 默认淘汰策略,对于写请求不再提供服务,直接返回错误( DEL 请求和部分特殊请求除外)
all keys - lru
从所有 key 中使用 LRU 算法进行淘汰
volatile - lru
从设置了过期时间的 key 中使用 LRU 算法进行淘汰
all keys - random
从所有 key 中随机淘汰数据
volatile - random
从设置了过期时间的 key 中随机淘汰
volatile - ttl
从设置了过期时间的 key 中,根据 key 的过期时间进行淘汰,越早过期的越优先被淘汰
当使用volatile-lru、volatile-random、volatile-ttl这三种策略时,如果没有key可以被淘汰,则和noeviction一样返回错误
LRU算法
又称最近最少使用算法,它的基本思想是长期不被使用的数据,在未来被用到的几率也不大,所以当新的数据进来时我们可以优先把这些数据替换掉。
key的删除策略
定时删除
含义:在设置key的过期时间的同时,为该key创建一个定时器,让定时器在key的过期时间来临时,对key进行删除
优点:保证内存被尽快释放
缺点:若过期key很多,删除这些key会占用很多的CPU时间,在CPU时间紧张的情况下,CPU不能把所有的时间用来做要紧的事儿,还需要去花时间删除这些key
定时器的创建耗时,若为每一个设置过期时间的key创建一个定时器(将会有大量的定时器产生),性能影响严重没人用
惰性删除
含义:key过期的时候不删除,每次从数据库获取key的时候去检查是否过期,若过期,则删除,返回null。
优点:删除操作只发生在从数据库取出key的时候发生,而且只删除当前key,所以对CPU时间的占用是比较少的,而且此时的删除是已经到了非做不可的地步(如果此时还不删除的话,我们就会获取到了已经过期的key了)
缺点:若大量的key在超出超时时间后,很久一段时间内,都没有被获取过,那么可能发生内存泄露(无用的垃圾占用了大量的内存)
定期删除
含义:每隔一段时间执行一次删除过期key操作
优点:通过限制删除操作的时长和频率,来减少删除操作对CPU时间的占用
缺点:在内存友好方面,不如"惰性删除" 在CPU时间友好方面,不如"定时删除"
难点:合理设置删除操作的执行时长(每次删除执行多长时间)和执行频率(每隔多长时间做一次删除)(这个要根据服务器运行情况来定了)
redis锁的两种意外
a.如果redis中的锁已经过期了,然后锁过期的那个请求又执行完毕,回来删锁,删除的是其他线程的锁,怎么办?
答案:用key获取value值,判断value值与set时是否一致
b.如果碰巧在查询redis锁还没有删除的时候,正在网络传输时,锁过期了,怎么办?
jedis.eval(“lua”);可与用lua脚本,在查询到key的同时删除该key,防止高并发下的意外的发生
redis内存优化方案 lru
1、缩减key和value的长度。key尽量简写如s:a:id。value不存储不需要数据。
2、开启共享内存池,纯数字数据可以公用内存。但是无法使用过lru的内存淘汰策略
3、如果编辑数据长度变化较大,尽量删除后重新存储。因为redis的预分配机制,追加操作,将会预留更大的存储空间。
4、尽量使用复杂度更低的编码方式,编码方式不可逆。如果数据变简单,情况允许,可以重新创建。
5、控制hash中键的数量。数量最好不要超过1000。因为ziplist编码,超过1000后,cpu消耗增加
先整理到这吧 一句话 想要学好还是要先看底层