zoukankan      html  css  js  c++  java
  • Redis基础学习

    Redis简介

    Redis是完全开源免费的,遵守BSD协议是一个高性能的key-value数据库

    Redis与其他key-value缓存产品相比有以下三个特点:

    •   Redis支持数据持久化,可以将内存中的数据持久化到磁盘中,重启的时候可以再次加载到内存中。
    •   Redis不仅仅支持key-value类型的数据,同时还支持list,set,zset,hash,bloomFilter等数据结构的存储。
    •   Redis支持数据备份,即master-slave模式的数据备份。    

    Redis优势

    1、丰富的数据类型--Redis支持二进制案例的Strings,Lists,Hashes,Sets及Ordered Sets数据类型操作。

    2、高性能--Redis读的速度是110000次/s,写的速度是81000次/s.

    3、原子性--Redis的所有操作都是原子性的,即要么成功执行,要么失败全部不执行。单个操作是原子性的。多个操作也支持事物,即原子性,通过MULTI和EXEC指令包起来。

    4、其他特性--Redis还支持publish/subscribe通知,key过期等特性。

    Redis数据类型

    Redis支持5中数据类型,string(字符串),hash(哈希),list(列表),set(集合),zset(sorted set 有序集合)。

    string

    string是redis的基本数据类型,一个key对应一个value。string类型的值最大能存储512M

    string是二进制安全的,意思是redis的string可以包含任何数据,比如jpg图片或者序列化的对象。

    理解:string就像是java中的map一样,一个key对应一个value

    hash

    Redis hash 是一个键值对(key-value)的集合。

    Redis hash 是一个string类型的key和value的映射表,hash特别适合存储对象。

    理解:可以将hash看成是一个key-value的集合,也可以将其想像成一个hash对应着多个string。

    hash和string的区别:string是一个key-value的键值对,而hash是多个key-value的键值对。

    List

    Redis list是一个简单的字符串列表,按照插入顺序排序,我们可以向列表的左边或者右边添加元素。

    可以看出list就是一个简单的字符串集合,和java中的list相差不大,区别是这里的list存放的是字符串。list 中的元素是可重复的。

    set

    Redis的set是字符串类型的无序集合,集合是通过hash表实现的,因此添加、删除、查找的复杂度都是O(1)。

    类比java:Redis的set和java中的set还是有些区别的。Redis的set是一个key对应多个字符串类型的value,也是一个字符串类型的集合,但是和Redis的list不同的是set中的字符串集合元素不能重复,但是list可以。

    zset

    Redis的zset和set一样都是字符串类型元素的集合,并且集合内的元素不能重复。但是相比set,zset的每个元素都会关联一个double类型的分数(score)。Redis通过分数为集合中的成员进行从小到大的排序。zset的元素是唯一的,但是分数(score)可以重复。

    小结:

    string二进制可以包含任何数据,比如jpg图片或者序列化的对象,一个键最大能存储521M

    hash键值对集合,即编程语言中的map类型适合存储对象,并且可以像数据库中update一样只修改某一项属性值存储、读取、修改用户属性。

    list双向链表增删快,提供了操作某一段元素的API,

    • 最新消息排行等功能(朋友圈时间线)
    • 消息队列

    set 哈希表实现,元素不能重复,添加删除查找的复杂度都是O(1),为集合提供了求交集、并集、差集等操作共同好友;利用唯一性,统计访问网站的所有独立ip;好友推荐时根据tag求交集,大于某个阈值就可以推荐。

    zset将set中的元素增加一个权重参数score,元素按照score有序排列数据插入集合时,已经进行天然排序,排行榜,带权重的消息队列。

    Redis常见问题

    1、如果有大量的key需要设置同一时间过期,一般需要注意什么?

    如果大量的key过期时间设置的过于集中,到了过期的那个时间点,redis可能会出现短暂的卡顿现象。严重的话会出现缓存雪崩,我们一般需要在过期时间上加一个随机值,使得过期时间分散一些。

    2、假如redis中有1亿个key,其中10w个key是以某一个 固定的已知前缀 开头,如何将他们全部找出来?

    使用keys指令可以扫出指定模式的key列表。

    3、如果这个redis正在给线上的业务提供服务,那使用keys指令会有什么问题?

    此问题涉及到redis的一个关键特性:redis是单线程的。Keys指令会导致线程阻塞一点时间,线上服务会卡顿,直到指令执行完毕,服务才能恢复。这个时候可以使用scan指令,scan指令可以无阻塞的提取出指定模式的key列表,但是会有一定的重复概率,在客户端做一次去重就可以了,但是整体所花费的时间会比直接用keys指令长。

    4、Redis是如何持久化的,服务主从数据是怎么交互的?

    RDB做镜像全量持久化,AOF做增量持久化。主要是因为RDB会耗费较长时间,不够实时,在停机的时候会导致大量丢失数据,所以需要AOF来配合使用。在redis实例重启的时候,会使用RDB持久化文件重新构建内存,在使用AOF重放近期的操作指令来实现完整回复重启之前的状态。Redis机制是AOF持久化开启且存在AOF文件时,优先加载AOF文件;AOF关闭或者AOF文件不存在时,加载RDB文件;加载AOF/RDB文件后,Redis启动成功;AOF/RDB文件存在错误时,Redis启动失败并打印错误信息;

    5、什么是缓存雪崩?如何解决?

     

    通常情况下,我们使用缓存用于缓冲对DB的冲击,如果缓存宕机,所有请求将直接打在DB上,造成DB宕机,从而导致整个系统宕机。

    解决方案:

    2种策略(同时使用)

    1、对缓存做高可用,防止缓存宕机

    2、使用断路器,如果缓存宕机,为了防止系统全部宕机,限制部分流量进入DB,保证部分可用,其余请求返回断路器的默认值。

    6、什么是缓存穿透,怎么解决?

    在缓存查询一个没有的key,同时数据库也没有,如果黑客大量使用这种方式,那么就会导致DB宕机。

    解决方案:

    A:可以使用一个默认值来防止,例如,当访问一个不存在的key时,然后再去访问数据库还是没有,那么就在缓存中放一个占位符,下次在访问时,检查这个占位符,如果查到占位符,则不再查询数据库,防止DB宕机。

    B:Redis还有一个高级用法布隆过滤器(Bloom Filter)这个也能很好的防止缓存穿透的发生,他的原理也很简单就是利用高效的数据结构和算法快速判断出你这个Key是否在数据库中存在,不存在你return就好了,存在你就去查了DB刷新KV再return。

    7、什么是缓存击穿,怎么解决?

    大量请求查询一个刚刚失效的key,导致DB压力倍增,可能导致宕机,但实际上查询的都是相同的数据。

    解决方案:可以在这些请求代码加上双重检查锁。但是那个阶段的请求会变慢。设置热点数据永远不过期

    8、Redis 的过期策略

    Redis采用的是 定期删除 + 懒惰删除策略

    定期删除策略

    Redis 会将每个设置了过期时间的 key 放入到一个独立的字典中,默认每 100ms 进行一次过期扫描:

    1、随机抽取 20 个 key

    2、删除这 20 个key中过期的key

    3、如果过期的 key 比例超过 1/4,就重复步骤 1,继续删除。

    9、为什不扫描所有的 key?

    Redis 是单线程,全部扫描岂不是卡死了。而且为了防止每次扫描过期的 key 比例都超过 1/4,导致不停循环卡死线程,Redis 为每次扫描添加了上限时间,默认是 25ms。

    如果客户端将超时时间设置的比较短,比如 10ms,那么就会出现大量的链接因为超时而关闭,业务端就会出现很多异常。而且这时你还无法从 Redis 的 slowlog 中看到慢查询记录,因为慢查询指的是逻辑处理过程慢,不包含等待时间。

    如果在同一时间出现大面积 key 过期,Redis 循环多次扫描过期词典,直到过期的 key 比例小于 1/4。这会导致卡顿,而且在高并发的情况下,可能会导致缓存雪崩。

    为什么 Redis 为每次扫描添的上限时间是 25ms,还会出现上面的情况?

    因为 Redis 是单线程,每个请求处理都需要排队,而且由于 Redis 每次扫描都是 25ms,也就是每个请求最多 25ms,100 个请求就是 2500ms。

    如果有大批量的 key 过期,要给过期时间设置一个随机范围,而不宜全部在同一时间过期,分散过期处理的压力。

    从库的过期策略

    从库不会进行过期扫描,从库对过期的处理是被动的。主库在 key 到期时,会在 AOF 文件里增加一条 del 指令,同步到所有的从库,从库通过执行这条 del 指令来删除过期的 key。

    因为指令同步是异步进行的,所以主库过期的 key 的 del 指令没有及时同步到从库的话,会出现主从数据的不一致,主库没有的数据在从库里还存在。

    懒惰删除策略

    10、Redis 为什么要懒惰删除(lazy free)?

    删除指令 del 会直接释放对象的内存,大部分情况下,这个指令非常快,没有明显延迟。不过如果删除的 key 是一个非常大的对象,比如一个包含了千万元素的 hash,又或者在使用 FLUSHDB 和 FLUSHALL 删除包含大量键的数据库时,那么删除操作就会导致单线程卡顿。

    redis 4.0 引入了 lazyfree 的机制,它可以将删除键或数据库的操作放在后台线程里执行, 从而尽可能地避免服务器阻塞。

    ----结语:此文章纯粹是为了学习,同时也希望能帮助到各位读者。

  • 相关阅读:
    Asp.Net 构架(Http Handler 介绍) Part.2<转>
    大数据插入<转>
    网站开发技巧参考大全<转>
    qq校友好东西
    SQL2005存储过程解密 <转>
    用Lucene.net对数据库建立索引及搜索<转>
    用SharpDevelop3调试ASP.NET的方法
    【转】卢彦的利用xml实现通用web报表打印
    张仰彪第二排序法 <转>
    依赖注入那些事儿 <转>
  • 原文地址:https://www.cnblogs.com/4king/p/11808227.html
Copyright © 2011-2022 走看看