redis是一款基于c语言的key-value数据库,支持发布订阅模式,可以用来做缓存,还可以做消息队列,分布式锁等等
redis支持5种数据结构string,list,set,zset,hash
1.string使用简单动态字符串,不使用C语言的数组,可以保存二进制数据,C语言只能保存文本,获取字符串长度复杂度为O(1),C语言为O(N),C语言不保存长度,需要遍历。安全的api,能避免缓冲区溢出内存泄漏问题。常用命令set,get,strlen(字符串长度),exists,decr,incr,setex(设置比字符串及过期时间),mset(批量设置字符串),返回原值的 GETSET 命令。
2.list采用的是双向链表结构,因子插入,删除速度很快,定位索引很慢。LPUSH和RPUSH可以向链表的左(前)右(后)插入节点,LRANGE可以从链表中获取一定范围的数据(可以做分页),LINDEX可以指定获取第几个元素。LPOP取出头部元素并移除,RPUSH从尾部放入元素实现队列。RPOP取出并删除尾部元素,RPUSH放入元素实现先进后出的栈。LLEN获取链表长度。
3.hash相当于java里面的hashMap,采用数组+链表结构,使用链地址法解决hash冲突。redis采用渐式扩容,内部存有两个table数组。非常适合存储对象数据
渐式扩容:当元素个数达到数组的长度时,开始扩容,新数组的长度为原来的2倍,前提是redis不在持久化,当达到5倍时,就会强制扩容。当元素达到原来长度的10%,就会进行缩减,无论是否在持久化。
4.set是一种无序集合,相当于java里面的hashset,内部无序唯一,值都是NULL。应用于多个数据不能重复及多数据的交集,并集,差集。
5.zset相当于treeSet和hashMap的结合。set保证value唯一,map为每个value增加score属性,进行权重排序。可以应用于实时排行信息
6.bitmap存储为连续二进制0和1的位数组。适合保存状态信息,应用于用户签到,用户活跃,用户行为统计(例如点赞)等场景
redis 使用单线程多路IO复用技术
redis其他用途:分布式锁,消息队列,redis+lua(操作具有原子性)进行限流,Redisson数据结构丰富扩展(bitmap统计活跃用户,sorted set维护排行榜)
过期删除策略
惰性删除:每次获取key对应的value时判断key是否过期,对cpu友好,但容易造成大量数据未删除
定期删除:每一段时间抽取一批过期的key进行删除,为了减少对cpu时长的影响,redis会控制删除的时长和频率
内存淘汰机制(避免过期策略导致大量数据未删除)
1.从设置过期数据中筛选最少最少使用
2.从设置过期数据中筛选将要过期
3.从设置过期数据中任意淘汰
4.当内存不足时,删除最少使用
5.从数据中选择任意淘汰
6.禁止删除,当内存不足禁止写入,报错
7.从设置过期数据中筛选最不经常使用的
8.当内存不足时,移除最不经常使用的
Redis持久化机制
1.快照:某个时间的内存副本
2.持久化文件:redis的每一条命令都会存到AOF文件中
redis采用混合方式持久化
Redis bigkey
1.redis string数据类型数据过大(10 kb)
2.非string类型元素过多(5000个)
危害:redis阻塞,内存空间不均匀,过期删除key可能阻塞(未采用redis异步过期删除)
发现:bigkeys参数每次可以查找每种数据结构的最大的一个bigkey及健值对个数和平均大小
处理:(1)异步删除操作;(2)SCAN部分读取后删除;(3)拆分字符串或元素数量;(4)存数据库(mysql,MongoDB)
Redis事物
提供一种将多个命令打包的功能,按顺序执行,命令不会被中断,不支持回滚。
Redis提供stream数据结构做消息队列。支持持久化(两种),消费组消费,发布订阅模型。
缓存穿透
key根本不在数据库中(黑客故意攻击)
解决:缓存无效的key,布隆过滤器
缓存雪崩
缓存同一时间大批量失效,大量的请求落到数据库中
解决:设置缓存永不过期;设置缓存不同的失效时间
缓存击穿
缓存中没有,数据库有,大致请求都到数据库中
加互斥锁按key去查数据,热点数据不过期