redis
是什么、为什么
What(是什么?)
Redis 是一个高性能的key-value内存数据库。它支持常用的5种数据结构:String字符串、Hash哈希表、List列表、Set集合、Zset有序集合 等数据类型。
解决了什么问题
第一个是:性能
通常数据库的读操作,一般都要几十毫秒,而redisd的读操作一般仅需不到1毫秒。通常只要把数据库的数据缓存进redis,就能得到几十倍甚至上百倍的性能提升。
第二个是:并发
在大并发的情况下,所有的请求直接访问数据库,数据库会出现连接异常,甚至卡死在数据库中。为了解决大并发卡死的问题,一般的做法是采用redis做一个缓冲操作,让请求先访问到redis,而不是直接访问数据库。
存储类型: 字符串 string,列表 list,集合 set,散列 hash,有序集合 zset。
功能场景
- string
- 微信文章的阅读量PV场景
- 购物车
- cookie
- 自动补全
- 网页缓存
- 分布式锁
- 数据行缓存
- 记录日志
- 计数器
- 统计数据
- ip地址
- 服务注册与发现 dubbo
- list List类型是一个双端链表的结构,其主要功能有push、pop、获取元素等;一般应用在栈、队列、消息队列等场景。
- 二级缓存的高并发微信文章的阅读量PV (数量先放在Map中,再定时移入redis中)
- 分页 数据量少,高并发、请求量大。电商的首页中的滚动数据,或少量分页数据
- 队列 lpush rpop (一生产一消费情形)
- set
- 交集、并集、是否包含,黑名单,点赞/取消,抽奖(无限商品与有限商品,无限商品用srandmember命令,即随机返回set的一个元素、有限商品用spop命令,即随机返回并删除set中一个元素)
- string
已使用过
- 权限数据缓存
CONFIG GET maxclients
config get timeout | config set timeout 300
检查服务端tcp连接:netstat -nat|grep -i "6379"|wc -l
执行client list命令,发现大量的client的idle时间特别长:
命令
- dbsize 显示当前库key的数量
info可以看到所有库的key数量
- keys
- hgetall
- RANDOMKEY
set key1 value1
get key1
del key1
get key1
scan 11 match abc:* count 10
http://redis.io/commands/slowlog
SLOWLOG get 10
常见问题
缓存穿透、缓存击穿、缓存雪崩
前台请求,后台先从缓存中取数据,取到直接返回结果,取不到时从数据库中取,数据库取到更新缓存,并返回结果,数据库也没取到,那直接返回空结果。
https://img-blog.csdn.net/20180919143214712
缓存穿透
缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求,如发起为id为“-1”的数据或id为特别大不存在的数据。这时的用户很可能是攻击者,攻击会导致数据库压力过大。
解决方案:
- 接口层增加校验,如用户鉴权校验,id做基础校验,id<=0的直接拦截;
- 从缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value对写为key-null,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用)。这样可以防止攻击用户反复用同一个id暴力攻击
- 缓存穿透可以用布隆过滤器解决
- 从元素的角度来说:如果元素实际存在,布隆过滤器一定判断存在,如果元素实际不存在,布隆过滤器可能判断存在。(误判)
- guava中有实现,单机版
- redis的位图bitmap
缓存击穿
缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力
缓存击穿指并发查同一条数据的情况。
解决方案:
设置热点数据永远不过期。
加互斥锁,互斥锁参考代码如下:
https://img-blog.csdn.net/20180919143214879
说明:
1)缓存中有数据,直接走上述代码13行后就返回结果了
2)缓存中没有数据,第1个进入的线程,获取锁并从数据库去取数据,没释放锁之前,其他并行进入的线程会等待100ms,再重新去缓存取数据。这样就防止都去数据库重复取数据,重复往缓存中更新数据情况出现。
3)当然这是简化处理,理论上如果能根据key值加锁就更好了,就是线程A从数据库取key1的数据并不妨碍线程B取key2的数据,上面代码明显做不到这点。
缓存雪崩
缓存雪崩是指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机。和缓存击穿不同的是, 缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。
解决方案:
- 缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。
- 如果缓存数据库是分布式部署,将热点数据均匀分布在不同的缓存数据库中。
- 设置热点数据永远不过期。
◆缓存和数据库双写一致性问题
◆缓存的并发竞争问题
单线程的 Redis 为什么这么快?
这个问题是对 Redis 内部机制的一个考察。根据我的面试经验,很多人都不知道 Redis 是单线程工作模型。所以,这个问题还是应该要复习一下的。
◆纯内存操作
◆单线程操作,避免了频繁的上下文切换
◆采用了非阻塞 I/O 多路复用机制
Redis 的过期策略以及内存淘汰机制
这个问题相当重要,到底 Redis 有没用到家,这个问题就可以看出来。
比如你 Redis 只能存 5G 数据,可是你写了 10G,那会删 5G 的数据。怎么删的,这个问题思考过么?
还有,你的数据已经设置了过期时间,但是时间到了,内存占用率还是比较高,有思考过原因么?
回答:Redis 采用的是定期删除+惰性删除策略。
为什么不用定时删除策略
定时删除,用一个定时器来负责监视 Key,过期则自动删除。虽然内存及时释放,但是十分消耗 CPU 资源。
在大并发请求下,CPU 要将时间应用在处理请求,而不是删除 Key,因此没有采用这一策略。
定期删除+惰性删除是如何工作
定期删除,Redis 默认每个 100ms 检查,是否有过期的 Key,有过期 Key 则删除。
需要说明的是,Redis 不是每个 100ms 将所有的 Key 检查一次,而是随机抽取进行检查(如果每隔 100ms,全部 Key 进行检查,Redis 岂不是卡死)。
key设计原则
使用的数据结构:hashtable
hash 冲突/碰撞 头插法
rehash
- 主动
- 被动
redis源码
redis中key是字符串。
SDS: simple dynamic string
int len;
char[] buf;
集群
搜索 redis-cluster-readme.txt
【附件】redis-cluster-docker-compose-and-code.7z
batchRedis.txt
批量生成redis测试数据
1.Linux Bash下面执行
for((i=1;i<=20000000;i++)); do echo "set k$i v$i" >> /tmp/redisTest.txt ;done;
生成2千万条redis批量设置kv的语句(key=kn,value=vn)写入到/tmp目录下的redisTest.txt文件中
2.用vim去掉行尾的^M符号,使用方式如下::
dos2unix /tmp/redisTest.txt
3.通过redis提供的管道--pipe形式,去跑redis,传入文件的指令批量灌数据,需要花10分钟左右
cat /tmp/redisTest.txt | 路径/redis-5.0.0/src/redis-cli -h 主机ip -p 端口号 --pipe
https://blog.csdn.net/weixin_42509964/article/details/112482382
最后编辑:admin 更新时间:2025-09-19 10:08