Redis| 青训营笔记

92 阅读4分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 14 天

Redis概述

Redis是C语言开发的一个开源的(遵从BSD协议)高性能键值对(key-value)的内存数据库,可以用作数据库、缓存、消息中间件等。它是一种NoSQL(not-only sql,泛指非关系型数据库)的数据库。

Redis的特点

性能优秀,数据在内存中,读写速度非常快,支持并发10W QPS; 单进程单线程,是线程安全的,采用IO多路复用机制; 丰富的数据类型,支持字符串(strings)、散列(hashes)、列表(lists)、集合(sets)、有序集合(sorted sets)等; 支持数据持久化。可以将内存中数据保存在磁盘中,重启时加载; 主从复制,哨兵,高可用; 可以用作分布式锁; 可以作为消息中间件使用,支持发布订阅。

Redis的五种数据类型

1. String

String是Redis最基本的数据类型,一个key对应一个value。value是二进制安全的,可以存储jpg图片或者序列化对象,最大可存储512M。

2. Hash

hash类型存储键值对集合,类似于Java中的HashMap类型。hash类型特别适合存储对象,而且可以只修改对象中的某一个属性值。

3. List

List是字符串列表,本质实现方式是双向链表,插入的时候可以选择插入到队头或者队尾。在进行增删操作的时候效率很高,一般用于消息队列等场景。

4. Set

Set是String的无序类型,本质是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。Set可以用于判断共同好友、访问网站IP等需要去重的场合。

4. Set

Set是String的无序类型,本质是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。Set可以用于判断共同好友、访问网站IP等需要去重的场合。同list类似,Redis内部也不是直接使用的跳表,而是使用了一个自定义的数据结构来持有跳表。下图左边蓝色部分是skiplist,右边是4个zskiplistNode。zskiplistNode内部有很多层L1、L2等,指针指向这一层的下一个结点。BW是回退指针(backward),用于查找的时候回退。然后下面是score和对象本身object。

缓存问题

缓存和数据库数据一致性问题 分布式环境下非常容易出现缓存和数据库间数据一致性问题,针对这一点,如果项目对缓存的要求是强一致性的,那么就不要使用缓存。我们只能采取合适的策略来降低缓存和数据库间数据不一致的概率,而无法保证两者间的强一致性。合适的策略包括合适的缓存更新策略,更新数据库后及时更新缓存、缓存失败时增加重试机制。

Redis雪崩 当缓存中大面积的Key同时失效,使得本来作用于缓存的请求全部落在了数据库上,导致数据库崩溃,重启数据库时又被新的流量弄崩溃了,这就是缓存雪崩。

解决方案:

可以在批量往Redis存数据的时候,把每个Key的失效时间加个随机值,均匀分布缓存失效时间。 定时更新缓存。 Redis缓存穿透 缓存穿透是指缓存和数据库中都没有的数据,而用户(黑客)不断发起请求,导致一直在数据库里搜索,这样的不断攻击导致数据库压力很大,严重会击垮数据库。

解决方案:

在接口层增加校验,不合法的请求直接拦截掉。 Redis里还有一个高级用法**布隆过滤器(Bloom Filter)**这个也能很好的预防缓存穿透的发生,他的原理也很简单,就是利用高效的数据结构和算法快速判断出你这个Key是否在数据库中存在,不存在你return就好了,存在你就去查DB刷新KV再return。缓存击穿的话,设置热点数据永不过期,或者加上互斥锁就搞定了。 Redis缓存击穿 缓存击穿是指一个Key非常热点,在不停地扛着大量的请求,大并发集中对这一个点进行访问,当这个Key在失效的瞬间,持续的大并发直接落到了数据库上,就在这个Key的点上击穿了缓存。

解决方案:

对于热点请求的Key,设置数据永不过期。 对热点Key限流,大于接受量时阻塞。或者加上互斥锁。