Redis
1、描述什么是RedisTemplate
RedisTemplate是一个key和value都是泛型的模板类,一般情况下key为String类型
Spring封装了RedisTemplate对象,来进行对Redis的各种操作,它支持所有Redis原生的api。RedisTemplate位于spring-data-redis包下。RedisTemplate提供了redis各种操作、异常处理及序列化,支持发布订阅,并对spring 3.1 cache进行了实现。
2、string结构类型常用命令和应用场景
赋值语法:SET KEY_NAME VALUE: (说明:多次设置name会覆盖) (Redis SET 命令用于设置给定 key 的值。如果 key 已经存储值, SET 就覆写旧值,且无视类型)
取值语法: GET KEY_NAME : Redis GET命令用于获取指定 key 的值。如果 key 不存在,返回 nil 。如果key 储存的值不是字符串类型,返回一个错误。 GETRANGE key start end : 用于获取存储在指定 key 中字符串的子字符串。字符串的截取范围由 start 和 end 两个偏移量决定(包括 start 和 end 在内) DEL KEY_Name : 删除指定的KEY,如果存在,返回值数字类型。
STRLEN key : 返回 key 所储存的字符串值的长度
自增:INCRBY KEY_Name :增量值 Incrby 命令将 key 中储存的数字加上指定的增量值 自减:DECYBY KEY_NAME 减值 :DECR 命令将 key 中储存的数字减1
应用场景:
-1、String通常用于保存单个字符串或JSON字符串数据
-2、因String是二进制安全的,所以你完全可以把一个图片文件的内容作为字符串来存储
-3、计数器(常规key-value缓存应用。常规计数:微博数,粉丝数)
3、hash类型常用命令和应用场景
常用命令:
赋值语法:
HSETKEYFIELDVALUE:为指定的KEY,设定FILD/VALUE
取值语法:
HGETKEYFIELD:获取存储在HASH中的值,根据FIELD得到VALUE
删除语法:
HDELKEYfield1[field2]:删除一个或多个HASH表字段
应用场景:
1、常用于存储一个对象
如一个人的信息等
4、list类型常用命令和应用场景
赋值语法:
LPUSHkeyvalue1[value2]:将一个或多个值插入到列表头部(从左侧添加)
RPUSHkeyvalue1[value2]:在列表中添加一个或多个值(从右侧添加)
LPUSHXkeyvalue:将一个值插入到已存在的列表头部。如果列表不在,操作无效
RPUSHXkeyvalue:一个值插入已存在的列表尾部(最右边)。如果列表不在,操作无效。
取值语法:
LINDEXkeyindex:通过索引获取列表中的元素
LRANGEkeystartstop:获取列表指定范围内的元素
删除语法:
LPOPkey移出并获取列表的第一个元素(从左侧删除)
RPOPkey移除列表的最后一个元素,返回值为移除的元素(从右侧删除)
应用场景:
1、对数据量大的集合数据删减2、任务队列**
列表数据显示、关注列表、粉丝列表、留言评价等…分页、热点新闻、消息列表
5、set类型常用命令和应用场景
赋值语法:
SADDkeymember1[member2]
取值语法:
SCARDkey:获取集合的成员数
SMEMBERSkey:返回集合中的所有成员
删除语法:
SPOPkey[count]:移除并返回集合中的一个随机元素
应用场景:
对两个集合间的数据[计算]进行交集、并集、差集运算
共同关注、共同喜好、二度好友、统计访问网站的所有独立IP、存取某天的活跃用户列表
6、zset/hyperloglog类型常用命令和应用场景
ZADDkeyscore1member1[score2member2]:向有序集合添加一个或多个成员,或者更新已存在成员的分数
ZCARDkey:获取有序集合的成员数
ZCOUNTkeyminmax:计算在有序集合中指定区间分数的成员数
DELkey:移除集合
应用场景:
排行榜
HyperLogLog是用来做基数统计的算法
PFADDkeyelement[element...]:添加指定元素到HyperLogLog中
PFCOUNTkey[key...]:返回给定HyperLogLog的基数估算值
PFMERGEdestkeysourcekey[sourcekey...]:将多个HyperLogLog合并为一个HyperLogLog
应用场景:
统计注册IP数
统计每日访问IP数
统计页面实时UV数
统计在线用户数
统计用户每天搜索不同词条的个数
统计真实文章阅读数
7、描述什么是Redis事务?
Redis 事务可以一次执行多个命令,(按顺序地串行化执行,执行中不会被其它命令插入,不许加塞)
两个重要的保证: 1. Redis会将一个事务中的所有命令序列化,然后按顺序执行 2. 执行中不会被其它命令插入,不许出现加塞行为
8、Redis持久化机制有哪些,以及区别
RDB一定时间取存储文件,AOF默认每秒去存储历史命令,
RDB持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘
AOF持久化以日志的形式记录服务器所处理的每一个写、删除操作,查询操作不会记录,以文本的方式记录,可以打开文件看到详细的操作记录,并追加到文件中。
9、描述Redis缓存雪崩?解决方案
解决办法: 用锁/分布式锁或者队列串行访问 缓存失效时间均匀分布 数据预热
10、描述Redis缓存穿透?解决方案
缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,造成缓存穿透。
解决办法: 1、缓存空结果,但他的过期时间很短。 2、利用布隆过滤器,,拦截这个一定不存在的数据
11、对于热点key,有什么需要注意的?解决方案
热点key: 某个key访问非常频繁,当key失效的时候有大量线程来构建缓存,导致负载增加,且这是会有大量请求去查询数据库,可能挂掉数据库,使系统崩溃。
解决方案:1 使用锁,单机用synchronized,lock等,分布式用分布式锁。2 不设置key缓存过期时间,而是设置在key对应的value里。如果检测到存的时间超过过期时间则异步更新缓存。3在value设置一个比过期时间t0小的过期时间值t1,当t1过期的时候,延长t1并做更新缓存操作。4设置标签缓存,标签缓存设置过期时间,标签缓存过期后,需异步地更新实际缓存
12、Redis缺点是什么?说出解决方案
缺点: 耗内存 解决方案: 1、加内存 2、给数据key加上过期时间 3、配置redis数据淘汰策略
13、你的项目中,是如何将Redis和数据库数据进行同步的?
redis同步到数据库: 对于一部分重要的数据采用 异步队列 的方式同步到数据库,其他的数据采用 定时同步 到数据库
数据库同步到redis:数据预热`及 加锁排队:
先进行数据预热,将数据先一步加载到缓存中,
对于数据库中新添加的数据采用加锁排队的方式加载数据,防止缓存穿透、雪崩等异常
(一)缓存和数据库双写一致性问题 解决方案: 1、实时同步 2、异步队列 3、使用阿里的同步工具canal 4、采用UDF自定义函数的方式(二)缓存穿透 解决办法: 持久层查询不到就缓存空结果,查询时先判断缓存中是否exists(key) ,如果有直接返回空,没有则查询后返回,注意insert时需清除查询的key,否则即便DB中有值也查询不到(当然也可以设置空缓存的过期时间): 1、不管数据实际上存不存在,我们都把这个键存到缓存中(有效期设置的短一些,比如一分钟到三分钟),然后值设置为一个特定值,业务中如果获取到的结果是这个特定值,则报错返回。
、 2、是使用 redis 的布隆过滤器(Bloom Filter),将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被 这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。
(二)缓存雪崩问题 解决方案: 用锁/分布式锁或者队列串行访问 缓存失效时间均匀分布 1 加锁排队. 限流-- 限流算法. 2 数据预热(三)缓存击穿问题 解决方案: 1 使用锁,单机用synchronized,lock等,分布式用分布式锁。 2 缓存过期时间不设置,而是设置在key对应的value里。如果检测到存的时间超过过期时间则异步更新缓存。 3在value设置一个比过期时间t0小的过期时间值t1,当t1过期的时候,延长t1并做更新缓存操作。 4设置标签缓存,标签缓存设置过期时间,标签缓存过期后,需异步地更新实际缓存
(四)缓存的并发竞争问题 解决方案: (1)如果对这个key操作,不要求顺序这种情况下,准备一个分布式锁,大家去抢锁,抢到锁就做set操作即可,比较简单。 (2)如果对这个key操作,要求顺序假设有一个key1,系统A需要将key1设置为valueA,系统B需要将key1设置为valueB,系统C需要将key1设置为valueC.期望按照key1的value值按照 valueA-->valueB-->valueC的顺序变化。这种时候我们在数据写入数据库的时候,需要保存一个时间戳