一 redis-cli 操作 redis 五种数据类型
1.string
Set:添加一条 String 类型数据
Get:获取一条 String 类型数据
Mset:添加多条 String 类型数据
Mget:获取多条 String 类型数据
2.hash
Hset:添加一条 hash 类型数据
Hget:获取一条 hash 类型数据Hmset:添加多条 hash 类型数据
Hmget:获取多条 hash 类型数据
HgetAll:获取指定所有 hash 类型数据
hdel:删除指定 hash 类型数据(一条或多条)
3.list
Lpush:左添加(头)list 类型数据
Rpush:右添加(尾)类型数据
Lrange: 获取 list 类型数据 start 起始下标 end 结束下标 包含关系
llen:获取条数
lrem:删除列表中几个指定 list 类型数据
4.set
Sadd:添加 set 类型数据
Smembers:获取 set 类型数据
scard:获取条数
srem:删除数据
5.sorted set(有序列表)
sorted set 是通过分数值来进行排序的,分数值越大,越靠后。
Zadd:添加 sorted set 类型数据
Zrange:获取 sorted set 类型数据
zcard:获取条数
zrem:删除数据
注意: Zadd 需要将 Float 或者 Double 类型分数值参数,放置在值参数之前
二 设置 key 的失效时间
三 如何应对缓存穿透、缓存击穿、缓存雪崩问题
1.缓存穿透
是指查询一个数据库一定不存在的数据。正常的使用缓存流程大致是,数据 查询先进行缓存查询,如果 key 不存在或者 key 已经过期,再对数据库进行查询,并把查 询到的对象,放进缓存。如果数据库查询对象为空,则不放进缓存,就会每次都去查询数据 库,而每次查询都是空,每次又都不会进行缓存。假如有恶意攻击,就可以利用这个漏洞, 对数据库造成压力,甚至压垮数据库,导致所有的请求都怼到数据库上,从而数据库连接异 常。
解决方案:
(1)利用互斥锁,缓存失效的时候,先去获得锁,得到锁了,再去请求数据库。没得到 锁,则休眠一段时间重试
(2)采用异步更新策略,无论 key 是否取到值,都直接返回。value 值中维护一个缓存 失效时间,缓存如果过期,异步起一个线程去读数据库,更新缓存。需要做缓存预热(项目 启动前,先加载缓存)操作。
(3)提供一个能迅速判断请求是否有效的拦截机制,比如,利用布隆过滤器,内部维护 一系列合法有效的 key。迅速判断出,请求所携带的 Key 是否合法有效。如果不合法,则直 接返回。
(4) 如果从数据库查询的对象为空,也放入缓存,只是设定的缓存过期时间较短,比如 设置为 60 秒。
2.缓存击穿
缓存击穿,是指一个 key 非常热点,在不停的扛着大并发,大并发集中对这一个点进行 访问,当这个 key 在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个 屏障上凿开了一个洞。做电商项目的时候,把这货就称为“爆款”。
解决方案:
其实,大多数情况下这种爆款很难对数据库服务器造成压垮性的压力。达到这个级别的 公司没有几家的。所以,对主打商品都是早早的做好了准备,让缓存永不过期。即便某些商 品自己发酵成了爆款,也是直接设为永不过期就好了。
(1) 从 redis 上看,确实没有设置过期时间,这就保证了,不会出现热点 key 过期问 题,也就是“物理”不过期。
(2) 从功能上看,如果不过期,那不就成静态的了吗?所以我们把过期时间存在 key 对应的 value 里,如果发现要过期了,通过一个后台的异步线程进行缓存的构建,也就是 “逻辑”过期。
3.缓存雪崩
缓存雪崩,是指缓存同一时间大面积的失效,这个时候又来了一波请求,结果请求都怼 到数据库上,从而导致数据库连接异常。
产生雪崩的原因之一,比如商城马上就要到双十一零点,很快就会迎来一波抢购,这波 商品时间比较集中的放入了缓存,假设缓存一个小时。那么到了凌晨一点钟的时候,这批商 品的缓存就都过期了。而对这批商品的访问查询,都落到了数据库上,对于数据库而言,就 会产生周期性的压力波峰。 其实集中过期,倒不是非常致命,比较致命的缓存雪崩,是缓存服务器某个节点宕机或 断网。因为自然形成的缓存雪崩,一定是在某个时间段集中创建缓存,那么那个时候数据库 也是可以顶住压力的,无非就是对数据库产生周期性的压力而已。而缓存服务节点的宕机, 对数据库服务器造成的压力是不可预知的,很有可能瞬间就把数据库压垮。
解决方案:
做电商项目的时候,一般是采取不同分类商品,缓存不同周期。在同一分类中的商品,加上一个随机因子。这样能尽可能分散缓存过期时间,而且,热门类目的商品缓存时间长一 些,冷门类目的商品缓存时间短一些,也能节省缓存服务的资源。
(1)给缓存的失效时间,加上一个随机值,避免集体失效。
(2)使用互斥锁,但是该方案吞吐量明显下降了。
(3)双缓存。我们有两个缓存,缓存 A 和缓存 B。缓存 A 的失效时间为 20 分钟,缓存 B 不设失效时间。自己做缓存预热操作。然后细分以下几个小点
a. 从缓存 A 读数据库,有则直接返回
b. A 没有数据,直接从 B 读数据,直接返回,并且异步启动一个更新线程。
c. 更新线程同时更新缓存 A 和缓存