type
status
date
slug
summary
tags
category
icon
password
📝 主旨内容
1.Redis的通用命令
- keys:查看符合模板的所有的key,不建议在生产环境设备上使用
- del:删除一个指定的key
- exists:判断key是否存在
- expire:给一个key设置有效期,有效期到期时该key会自动删除
- ttl:查看一个key的剩余有效期
通过help [command] 可以查看一个命令的具体用法
2.String类型的常见命令
- set:添加或修改已经存在的一个String类型的键值对、
- get:根据key获取String类型的value
- mset:批量添加多个String类型的键值对、
- mget:根据多个key获取多个String类型的value
- incr:让一个整型的key自增1
- incrby:让一个整型的key自增并指定步长,例如:incrby num 2 (让num值自增2)
- incrbyfloat:让一个浮点类型的数字自增并指定步长
- setnx:添加一个String类型的键值对,前提是这个key不存在 否者不执行
- setex:添加一个String类型的键值对,并指定有效期
3.Key的层级格式
- Redis的key允许有多个单词形成层级结构, 多个单词使用 : 隔开
- 格式: 项目名:业务名:类型:id
- 如果value是一个java对象 例如一个user对象 则可以将对象序列化为json字符串后存储
4.Hash类型的常见命令
- hash key field value:添加或者修改hash类型key的filed的值
- hget key filed:获取一个hash类型key的filed值
- hmset:批量添加多个hash类型key的filed值
- hmget:批量获取多个hash类型key的filed值
- hgetall:获取一个hash类型的key中的所有的field和value
- hkeys:获取一个hash类型的key中的所有filed
- hvals:获取一个hash类型的key中的所有value
- hincrby:让一个hash类型key的字段自增并指定步长
- hsetnx:添加一个hash类型的key的值,前提是这个filed不存在 否则不执行
5.List类型的常见命令
- lpush key element... :像列表左侧插入一个或多个元素
- lpop key:移除并返回列表左侧的第一个元素,没有则返回nil
- rposh key element... : 向列表右侧插入一个或多个元素
- rpop key :移除并返回右侧的第一个元素
- lrange key star end:返回一段角标范围内的所有元素
- blpop和brpop:与lpop和rpop类似 只不过在没有元素时等待指定时间 而不是直接返回nil
6.Set类型的常见命令
- sadd key member... :向set中添加一个或多个元素
- srem key member...:移除set中的指定元素
- scard key: 返回set中元素的个数
- sismember key member:判断一个元素是否存在于set中
- smembers:获取set中的所有元素
- sinter key1 key2.... :求key1 和 key2的交集
- sdiff key1 key2... :求key1和key2的差集
- sunion key1 key2 ...: 求key1和key2的并集
7.SortedSet类型
Redis的SortedSet是一个可排序的set集合 与java中的TreeSet有些类似,但底层数据结构差别很大。
sortedSet中的每一个元素都带有一个score属性,可以基于score属性对元素排序,底层的实现就是一个跳表(SkipList)加hash表。
特性:可排序,元素不重复,查询速度快(经常用来实现排行榜的功能)
常见的命令:
- zadd key score member :添加一个或多个元素到sorted set。如果已经存在则更新其score值
- zrem key member:删除sorted set中的一个指定元素
- zscore key member: 获取sorted set 中的指定元素的score值
- zrank key member:获取sorted set中的指定元素的排名
- zcard key: 获取sorted set 中的元素个数
- zcount key min max:统计score值在给定范围内的所有元素的个数
- zincrby key increment member:让sorted set中的指定元素自增,步长为指定的increment值
- zrange key min max:按照score排序后 获取指定排名范围内的元素
- zrangebyscore key min max:按照score排序后 获取指定score范围内的元素
- adiff 、ainter、zunion:求差集、交集、并集
8.Redis中的事务
- 从输入multi命令开始 输入的命令都会依次进入命令队列中 但不会执行 直到输入exec后 Redis会将之前的命令队列中的命令依次执行
- 组队的过程中可以通过discard来放弃组队
- 组队中的某个命令出现了报告错误,执行时整个队列都会被取消
- 如果执行阶段某个命令报出了错误则只有报错的命令不会被执行
- 悲观锁:每次拿数据的时候都先上锁 这样别人想要拿这个数据就会block知道它拿到锁
- 乐观锁:每次拿数据的时候都会认为别人不会修改,所以不上锁,但是在更新的时候会判断以下在此期间别人有没有去更新这个数据,可以使用版本号等机制
在执行multi之前 先执行watch key1 [key2],可以监视一个或多个key 如果在事务执行之前这些key被其他命令所改动 那么事务将会被打断。
ab -n 1000 -c 100 -p ~/profile -T application/x-www-form-urlencoded http://192.168.33.18:8080/Seckill/doseckill
Redis的序列化和反序列化
1.RedisTemplate的RedisSerizlizer
Redistemplate可以接收任意Object作为值写入Redis 只不过写入前会把Object序列化成字节形式,默认采用jdk序列化。
可以去自定义RedisTemplate的序列化方式:
2.第二种序列化和反序列化的方式
在第一种方式中会往Redis中插入一些包、类的指向数据,这写数据是占有一定空间的,能否去除
为了在反序列化时知道对象类型,json序列化器会将类的class类型写入json结果中,存入redis,会带来额外的内存开销。
为了节省内存空间,我们并不会使用JSON序列化器处理value 而是统一使用String序列化器,要求只能存储String类型的key和value 当需要存储java对象时手动完成对象的序列化和反序列化。
应用问题解决
1.缓存穿透
- redis查询不到数据,就会一直查询数据库 导致数据库压力过大崩溃 就是缓存穿透
- 出现非正常url访问 (恶意攻击)
解决方案
- 对空值缓存:如果一个查询返回的数据为空(不管数据是否存在)我们仍然把这个空结果(null)进行缓存,设置空结果的过期时间会很短,最长不超过5分钟
- 设置可访问名单(白名单):使用bitmaps类型定义一个可以访问的名单,名单id作为bitmaps的偏移量,每次访问和bitmap里面的id进行比较,如果访问id不在bitmaps里面,进行拦截 不允许访问
- 采用布隆过滤器:
2.缓存击穿
- redis缓存击穿指当一个非常热门的key过期后同时有大量的并发请求过来此时会导致缓存没有起到作用请求都会穿透到数据库层导致数据库压力骤增。
解决方案
- 预先设置热门数据:在redis高峰访问之前,把一些热门数据提前存入到redis里面,加大这些热门数据key的时长(设置热点数据永远不过期)
- 实时调整:现场监控哪些数据热门 实时调整key的过期时间
- 使用锁:(1)就是在缓存失效的时候(判断拿出来的值为空) 不是立即去 load db
(2)先使用缓存工具的某些带成功操作返回值的操作
3.缓存雪崩
- 在极少时间段,查询大量key的集中过期的情况
解决方案
(1)构建多级缓存架构:nginx缓存+redis缓存+其他缓存
(2)使用锁或者队列:用锁或者队列的方式保证来保证不会有大量的线程对数据库一次性进行读写,从而避免失效时大量的并发请求落到底层存储系统上,不适合高并发情况
(3)设置过期标志更新缓存:记录缓存数据是否过期(设置提前量)如果过期会触发通知另外的线程在后台去更新实际的key的缓存
(4)将缓存失效时间分散开:比如我们可以在原有的失效时间基础上增加一个随机值,比如1-5分钟随机,这样每一个缓存的过期时间的重复率就会降低
📎 参考文章
- 一些引用
- 引用文章
有关Notion安装或者使用上的问题,欢迎您在底部评论区留言,一起交流~
- 作者:三-岁
- 链接:https://mozhiyuan.top/article/b96a752c-72f5-4a6c-999a-e576f7d1e4de
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。