redis
redis基本概念
redis:用C语言开发基于NoSQL的键值型数据库。
特性:单线程,高性能(基于内存)
NoSQL数据库:非关系型数据库,数据以键值的形式存储,值的类型可以是文本、图片等,不同于SQL数据库只能存储基本类型数据。
redis数据结构
key值为字符串类型,value有5种数据结构(字符串:String,哈希:hash,列表:list,集合:set,有序集合:sortedset)
1.字符串:String
(1)存储 set key value
(2)获取 get key
(3)删除 del key
2.哈希:Hash
(1)存储 hset key field value
将哈希表 key 中的域 field 的值设为 value
(2)获取
hget key field
获取指定的field对应的值
hgetall key
获取所有的field和value
(3)删除 hdel key field
删除哈希表中key的一个field字段
3.列表:List(添加一个元素到头部或尾部)
(1)添加
lpush key value
将元素加入列表左边
rpush key value
将元素加入列表右边
(2)获取 lrange key start end
获取list的起止元素
(3)删除
lpop key
删除列表最左边的元素,并将元素返回
rpop key
删除列表最右边的元素,并将元素返回
4.集合:Set(不允许重复元素)
(1)存储 sadd key value
向无序的集合中增加一个元素
(2)获取 smembers key
获取set集合中所有元素
(3)删除 srem key value
删除set集合中的某个元素
5.有序集合:Sortedset(不允许重复元素,元素有序,每个元素关联一个double类型的分数)
(1)存储 zadd key score value
向有序集合添加一个成员
(2)获取 zrange key start end [withscores]
通过索引区间返回有序集合指定区间内的成员
(3)删除 zrem key value
移除有序集合中一个成员
6.key相关命令
1. keys * : 查询所有的键
2. type key : 获取键对应的value的类型
3. del key:删除指定的key value
4. exists key: 检查键是否存在
7.服务器命令(Ubuntu)
启动服务器:sudo service redis-server start
启动客户端:sudo redis-cli
测试redis:启动客户端后输入PING,连接成功会返回PONG。
redis其他问题
1.缓存穿透
1.1 产生原因
客户端请求的数据在缓存中和数据库中都不存在,这样缓存永远不会生效,这些请求都会访问数据库。导致DB的压力瞬间变大而卡死或者宕机。
大量的高并发的请求打在redis上
(1)这些请求发现redis上并没有需要请求的资源,redis命中率降低
(2)因此这些大量的高并发请求转向DB请求对应的资源
(3)DB压力瞬间增大,直接将DB打垮,进而引发一系列“灾害”
1.2 发生场景
(1)原来数据是存在的,但由于某些原因(误删除、主动清理等)在缓存和数据库层面被删除了,但前端或前置的应用程序依旧保有这些数据;
(2)恶意攻击行为,利用不存在的Key或者恶意尝试导致产生大量不存在的业务数据请求。
1.3 解决方法
(1)接口校验
对于无效访问直接拦截,不允许访问redis
(2)对空值进行缓存
没有这个id的数据,但可以把这个id缓存进redis,value值设置为null,即使被访问到这个值,可以直接返回一个null。
缺点:
(1)key的时间不能过长,以免浪费空间
(2)遇到大量攻击,需要设置大量的key,会造成空间的浪费
优点:
(1)实现简单,维护方便
(3)布隆过滤器
设置一个二进制数组0为不存在,1为存在,通过计算出哈希值,转换成二进制,存入这个数组,在客户端访问数据时,先访问布隆过滤器数据是否存在,不存在直接拒绝访问,存在进入redis访问。
缺点:
(1)实现复杂
(2)存在误判的可能,返回不存在,数据一定不存在,返回存在,数据也可能不存在
优点:
(1)内存占用少,没有多于的key
2.缓存击穿
2.1 产生原因
Redis中的某个热点key过期,但是此时有大量的用户访问该过期key。
2.2 解决方法
(1)互斥锁
只有一个请求可以获取到互斥锁,然后到DB中将数据查询并返回到Redis,之后所有请求就可以从Redis中得到响应
缺点:
(1)线程需要等待,性能受到影响
(2)可能有死锁的风险
优点:
(1)没有额外的内存消耗
(2)保证一致性
(3)实现简单
(2)逻辑过期
在value内部设置一个比缓存(Redis)过期时间短的过期时间标识,当异步线程发现该值快过期时,马上延长内置的这个时间,并重新从数据库加载数据,设置到缓存中去。
缺点:
(1)不保证一致性
(2)有额外性能消耗
(3)实现复杂
优点:
(1)线程无序等待,性能较好
3.缓存雪崩
3.1 产生原因
同一时间大量的缓存key同时失效或者redis服务宕机,导致大量请求到达数据库
3.2 解决方法
(1)将失效时间分散开
常用且易于实现通过使用自动生成随机数使得key的过期时间TTL是随机的,防止集体过期。
(2)给业务添加多级缓存
使用nginx缓存 + redis缓存 + 其他缓存,不同层使用不同的缓存,可靠性更强。
(3)构建缓存高可用集群
主要针对缓存服务故障的情景,使用Redis集群来提高服务的可用性。
(4)使用锁或者队列的方式
如果查不到就加上排它锁,其他请求只能进行等待,但这种方式可能影响并发量。