Redis学习笔记

Redis的数据结构及其使用场景

  • 字符串(String):Redis的分布式锁的实现使用的数据结构,可用于最简单的缓存,例如一个json字符串,计数器,Session共享,分布式ID
  • 哈希表(Hash):可用于存储key-value对,适合用于存储对象
  • 列表(List):Redis的列表根据指令的不同可当作列队或者栈来使用,可用于消息列队
  • 集合(Set):和列表类似,但是不能重复,可以实现交差并集操作
  • 有序集合(SortedSet):可以设置顺序

Redis是如何删除过期Key的

  • 惰性删除:当读/写某个key时,判读该key是否过期,如果过期则删除
  • 主动删除:由于惰性删除无法保证冷数据被及时清理,redis会定期(默认100ms)删除掉一批过期key

缓存雪崩,缓存穿透,缓存击穿

雪崩

缓存同一时间大面积失效,导致剩下的请求都落到数据库上,导致数据库短时间内承受大量请求崩掉
解决方案:

  • 缓存数据的过期时间随机设置,防止同一时间大量数据过期现象发生
  • 给每一个缓存数据增加相应的缓存标记,记录缓存是否失效,如果缓存标记失效则更新数据缓存。
  • 缓存预热
  • 互斥锁

穿透

缓存和数据库中都没有的数据,导致所有的请求都落到数据库上
解决方案:

  • 接口层增加校验
  • 从缓存和数据库都取不到的数据,可以将key-value写为key-null,缓存有效时间可以设置短一点,这样可以防止攻击用户反复用同一个key暴力攻击
  • 采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截,避免了对底层存储系统的查询压力。

击穿

缓存击穿是缓存中没有但是数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没有数据而去数据库读取,引起数据库压力瞬间增大,
造成过大压力。和缓存雪崩不同的是,缓存击穿指的是并发查询同一条数据,缓存雪崩是不同数据都过期了。
解决方案:

  • 设置热点数据永不过期
  • 加互斥锁

    Redis的持久化机制

    RDB:Redis DataBase

    (将某一时刻的内存快照,以二进制的方式写入磁盘)。
    手动触发:
  • save指令,使Redis处于阻塞状态,直到RDB持久化完成,才会响应其他客户端发来的指令,所以在生产环境要慎用。
  • bgsabe指令,fork一个子进程进行持久化,主进程旨在fork过程中有短暂的阻塞,子进程创建后,主进程就能响应客户端请求了。

自动触发;

  • save m n:在m喵内,如果有n个键发生改变,则自动触发持久化,通过bgsave执行,如果设置多个,只要满足其一条件就会触发,配置文件有默认配置。
  • flushall:用于清空redis的所有的数据库,flushdb清空当前redis所在数据库(默认是0号),会清空RDB文件,同时也会生出dump.rdb,内容为空。
  • 主从同步:全量同步时会自动触发bgsave指令,生成rdb发送给从节点。

优点

  1. 整个Redis数据库中只包含一个文件dump.rdb,方便持久化
  2. 容灾性号,方便备份
  3. 性能最大化,fork子进程来完成写操作,让主进程继续处理命令,所以是IO最大化,保证了redis的高性能
  4. 相对于数据集大时,比AOF的启动效率更高。

缺点

  1. 数据安全性低。RDB是隔一段时间进行持久化,如果持久化之间redis发生故障,会发生数据丢失。适用于对数据要求不严格的时候。
  2. 游湖是通过fork子进程来协助持久化的,因此数据集较大时,可能会导致服务器停止几百毫秒甚至一秒,会占用cpu。

AOF:Append Only File

以日志的形式来记录服务器处理的每一个写,删除操作,以文本的形式记录。

Redis使用遇到的坑

本来想着把本机上运行的redis迁移到docker,打算把原有配置文件直接映射过去,一顿操作

1
2
3
4
5
docker run --name myredis
-v /usr/local/dockers/redis/redis.conf:/etc/redis/redis.conf
-v /usr/local/dockers/redis:/data
-p 6379:6379
-d redis:6.2.7 redis-server /etc/redis/redis.conf

docker ps -a一看,容器没启动,status Exited(0)
各种百度无果,最后想起来,redis.conf里的daemonize是yes,所以容器刚启动完成就退出了。。