写过这么多博客,太过散乱,待业阶段,写点总结
引言
第一次使用redis是用来做sparkStreaming的中间状态存储,比如用bitmap存储uid,记录当天的UV;或者用来做计数,本片文章结合作者使用的经历来聊一下redis
常用数据结构、使用习惯、使用场景(jedis和大数据场景)
作为一个普通的开发人员,接触更多的就是如何用?那些场景用?怎么用?我们总是在不段的学习,起初我也不知道redis多个槽可以作为库进行数据的隔离,到了第二家公司,使用更加规范。
0、多个db的切换
对于很多同学来说都比较熟悉,定义一个jedis,使用jedis.select(),来选择不同的库,主要场景是做数据的隔离,少量数据情况下可以直接对一个库进行flushDB(清空)的操作,或者在资源紧缺的情况下,区分业务,区分测试、生产库。
1、string
存储一个kv对 场景:存储最终计算结果,业务去取,比如今天13点一个小时的用户uv
2、list
存储一个队列,遵循有序队列的规则,先进先出 场景: 用户召回一个场景,用户实时点击的数据,存到list中,业务去取,类似于一个延迟队列,缺点是取完即丢、不可复现
3、map
存储多个kv对,相当于把相同特征的string放到同一表里 场景:统计各个品类每小时pv,涉及到时间和品类两个维度
4、set
set用于去重嘛 场景:精确统计某个行为下有哪些用户
5、zset
在set的基础上对存储的数据进行打分 场景:精确统计某个行为下有哪些用户,并且需要通过最早点击的时间进行排序
6、bitmap
通过二进制的方式进行散了统计 场景:统计当天用户的uv,一直写入,用bitcount来统计,缺点是不适合生产过多,每个都占用大量内存。
7、过期时间
牢记对临时使用的设置过期时间,否则爆内存,特别是按天做中间状态的
8、pipeline
用于批量插入和删除,控制好批次的大小
资源申请计算方式(结合业务场景)
我有用户300万,对于每个用户有10条文案,我用redis存储这批数据如何做到使用最小内存 1、用string存,最暴力的,user_id+message_id,68是存储一个的长度,用命令(memory usage key,要求redis4.0及以上版本) 2、用zset,zset元素小于128个,大小小于64k的时候内部使用ziplist,其他底层都是hash 3、set同理 可以看到zset最小,是另外两个的1/4。
见过的问题
1、无过期时间,内存爆掉 2、穿透、雪崩 常见的是用redis作为mysql的缓存,先访问redis,redis没有再访问mysql,从mysql加载到redis,并设置过期时间,如果说过期时间比较集中,就会在某一时刻大量key失效,导致所有请求打到mysql上,对mysql产生巨大压力,做好随机过期策略 3、使用bitmap不规范,内存爆掉
运维知识
1、事务机制:redis事不支持回滚,语法错误不运行,运行错误之运行正确的 2、redis单线程
- 为什么不用多线程?
1)纯内存操作 2)多线程会出现上下文切换的损耗 3)路非阻塞I/O多路复用机制:多个请求发出socket,一个线程按照一定的顺序去执行 - 存在问题?
QPS超过10w+会出现瓶颈 - 如何解决?
1)提高配置 2)主从架构–读写分离
3、虚拟槽
4、架构
5、过期策略
- 惰性删除:自带的内置策略,在查询的时候检查是否过期
- 定时删除:在设置时间的时候,为key设置一个定时器,到期删除,配置中设置,浪费cpu
- 定期删除:每隔一段时间执行一次删除,配置中设置
6、replication机制 采用异步的方法,复制数据到slave节点,2.8以后,slaveNode周期性的确认自己每次复制的数据量 7、持久化 - rdb:将全量数据以二进制的形式写到文件的数据快照,一般T+1进行生成,作为备份
- aof:在缓存区将执行命令存储到文件中,并通过重写来维护文件的大小,AOF 的默认策略为每秒钟fsync一次
- 相同数据量下,aof文件更大,建议备份的时候两者混合使用
待续。。。
|