• redis


    redis

    一.什么是redis

    高性能的key-value数据库 , 支持的数据结构类型包括:字符串(String)、链表(list)、哈希表(hash)、集合(set)、有序集合(Zset)等。为了保证读取的效率,redis把数据对象都存储在内存当中,它可以支持周期性的把更新的数据写入磁盘文件中。

    二.redis集群

    文章:https://www.jianshu.com/p/84dbb25cc8dc

    视频: https://www.bilibili.com/video/av73287780?from=search&seid=17109570147136350701

    三.redis逐出算法

    MySQL里有1000w数据,redis中只存10w的数据,如何保证redis中的数据都是热点数据

    1.voltile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰

    2.volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰

    3.volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰

    4.allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰

    5.allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰

    6.no-enviction(驱逐):禁止驱逐数据

    四.redis删除策略

    redis采用的方式:定期删除+惰性删除

    定时删除

    创建一个定时器,当key设置有过期时间,且过期时间到达时,由定时器任务立即执行对键的删除操作
    优点:节约内存,到时就删除,快速释放掉不必要的内存占用
    缺点:CPU压力很大,无论CPU此时负载量多高,均占用CPU,会影响redis服务器响应时间和指令吞吐量
    总结:用处理器性能换取存储空间 (拿时间换空间)

    惰性删除

    数据到达过期时间,不做处理。等下次访问该数据时执行,如果未过期,返回数据,发现已过期,删除,返回不存在。

    优点:节约CPU性能,发现必须删除的时候才删除

    缺点:内存压力很大,出现长期占用内存的数据

    总结:用存储空间换取处理器性能(拿空间换时间)

    定期删除

    redis 会将每个设置了过期时间的 key 放入到一个独立的字典中,以后会定期遍历这个字典来删除到期的 key。

    Redis 默认会每秒进行十次过期扫描(100ms一次),过期扫描不会遍历过期字典中所有的 key,而是采用了一种简单的贪心策略。从过期字典中随机 20 个 key;删除这 20 个 key 中已经过期的 key;如果过期的 key 比率超过 1/4,那就重复步骤 1;

    五.redis事务

    https://blog.csdn.net/azurelaker/article/details/85045220 (深入理解Redis事务)

    六.redis持久化

    1.AOF:以追加的方式记录Redis的写操作,并在Redis重启时进行重放(与MySQL的binlog日志的原理是一样的)。当AOF日志过大时,redis支持日志重写。【在Redis中是先执行命令再记录日志到AOF,这也是Redis事务不支持回滚的原因:即使发生异常,没有可以用来执行回滚操作的日志。而传统的数据库例如MySQL都是先做日志然后再做操作,所以能够支持回滚】

    AOF的原理:操作系统将写操作首先记录到内存缓冲区中,然后使用fsync函数将数据刷新到磁盘中。

    AOF优点:如果不考虑性能,AOF可以最大限度保证数据完整性,可以设置每发生一次写操作就调用一次fsync函数;更加灵活,可以使用不同的fsync策略,完全不使用fsync,每秒使用fsync(默认),以及每次查询时使用fsync;

    缺点:与下面的RDB方式相比,相同数据集大小AOF占用空间更大;若调用fsync的频率过快,性能会变差;

    AOF文件损坏?AOF文件中可能有一条命令是不完整的,比如发生正在写入的时候断电的这种情况,redis支持重放这样的AOF文件,他会在启动日志中记录错误命令的行数,并在重放时对该行进行忽略。

    2.RDB:也称快照方式,配置每隔一段时间执行一次全量备份,Redis将数据集快照保存在磁盘上,保存在一个名为dump.rdb的二进制文件中,也可以手动调用SAVE或BGSAVE命令。

    RDB的原理:主进程调用fork函数生成一个子进程,子进程进行磁盘I/O操作,操作完成后替换旧的RDB文件

    RDB优点:非常适合做备份与回滚到指定的时间点,例如我们可以每天晚上2点执行定时计划全量备份一次Redis中的数据,以后我们进行恢复的时候可以将Redis恢复到指定的时间点的版本;与AOF相比使用RDB方式性能较高;与AOF相比Redis重启的速度较快;当AOF文件变的过大时可以自动进行重写(2.4版本以上,2.4以下版本需要手动调用)

    RDB的缺点:相比AOF丢失的数据可能会更多,比如设置5分钟备份一次快照,那么最多会损失5分钟的数据。

    3.混合方式:RDB与AOF混合使用。将 RDB文件的内容和增量的 AOF 日志文件存在一起。这里的 AOF 日志不再是全量的日志,而是自持久化开始到持久化结束的这段时间发生的增量 AOF 日志。

    七.redis常见问题

    缓存穿透

    一般是黑客故意去请求缓存中不存在的数据,导致所有的请求都落到数据库上,造成数据库短时间内承受大量请求而崩掉。

    解决方案
    1.布隆过滤器:将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。将数据通过哈希函数以0,1的方式存在bit数组(位数组)里。影响布隆过滤器效率的是:数组size,哈希函数个数;(缺点:布隆过滤器里数据无法进行删除操作)

    有很多种方法可以有效地解决缓存穿透问题,最常见的则是采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。另外

    2.缓存空对象:一个查询返回的数据为空(不管是数据不存在,还是系统故障),我们仍然把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。(缺点:空值的键值对会占用大量内存)

    缓存雪崩

    指在我们设置缓存时采用了相同的过期时间,缓存同一时间大面积的失效,所以,后面的请求都会落到数据库上,造成数据库短时间内承受大量请求而崩掉。

    解决方案
    事前:尽量保证整个 redis 集群的高可用性,发现机器宕机尽快补上。选择合适的内存淘汰策略。或在原有的失效时间基础上增加一个随机值,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件。
    事中:本地ehcache缓存 + hystrix限流&降级,避免MySQL崩掉
    事后:利用 redis 持久化机制保存的数据尽快恢复缓存

    缓存击穿(热点key)

    对于一些设置了过期时间的key,如果这些key可能会在某些时间点被超高并发地访问,是一种非常“热点”的数据。这个时候,需要考虑一个问题:缓存被“击穿”的问题,这个和缓存雪崩的区别在于这里针对某一key缓存,前者则是很多key。缓存在某个时间点过期的时候,恰好在这个时间点对这个Key有大量的并发请求过来,这些请求发现缓存过期一般都会从后端DB加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端DB压垮。

    解决方案
    1.使用互斥锁(mutex key)

    业界比较常用的做法,是使用mutex。简单地来说,就是在缓存失效的时候(判断拿出来的值为空),不是立即去load db,而是先使用缓存工具的某些带成功操作返回值的操作(比如Redis的SETNX或者Memcache的ADD)去set一个mutex key,当操作返回成功时,再进行load db的操作并回设缓存;否则,就重试整个get缓存的方法。
    SETNX,是「SET if Not eXists」的缩写,也就是只有不存在的时候才设置,可以利用它来实现锁的效果。
    "提前"使用互斥锁(mutex key)
    2.永不过期
    (1) 从redis上看,确实没有设置过期时间,这就保证了,不会出现热点key过期问题,也就是“物理”不过期。
    (2) 从功能上看,如果不过期,那不就成静态的了吗?所以我们把过期时间存在key对应的value里,如果发现要过期了,通过一个后台的异步线程进行缓存的构建,也就是“逻辑”过期

    3.维护过期时间

    在value内部设置1个超时值(timeout1), timeout1比实际的memcache timeout(timeout2)小。当从cache读取到timeout1发现它已经过期时候,马上延长timeout1并重新设置到cache。然后再从数据库加载数据并设置到cache中。

    八.redis常见性能问题和解决方案

    (1) Master最好不要做任何持久化工作,如RDB内存快照和AOF日志文件
    (2) 如果数据比较重要,某个Slave开启AOF备份数据,策略设置为每秒同步一次
    (3) 为了主从复制的速度和连接的稳定性,Master和Slave最好在同一个局域网内
    (4) 尽量避免在压力很大的主库上增加从库
    (5) 主从复制不要用图状结构,用单向链表结构更为稳定,即:Master <- Slave1 <- Slave2 <- Slave3…
    这样的结构方便解决单点故障问题,实现Slave对Master的替换。如果Master挂了,可以立刻启用Slave1做Master,其他不变。

    九.redis相比memcached的优势

    (1) memcached所有的值均是简单的字符串,redis作为其替代者,支持更为丰富的数据类型
    (2) redis的速度比memcached快很多 , 速度快:使用标准C写,所有数据都在内存中完成,读写速度分别达到10万/20万 . Memcached是多线程,分为监听线程、worker线程,引入锁,带来了性能损耗。Redis使用单线程的IO复用模型(redis单线程,避免了线程切换、加锁等资源消耗,redis内存处理比较快。多路io复用,多个socket链接复用, 使用同一个线程处理使用epoll策略,实现哪些socket有通讯,处理那些socket、 高效),将速度优势发挥到最大,也提供了较简单的计算功能。
    (3) redis可以持久化其数据

  • 相关阅读:
    poj 3411 Paid Roads
    uva 111 A History Grading
    hdu 4248 A Famous Stone Collector
    阶乘模版
    uva Coin Change
    POJ图论分类
    求 组合数 dp
    判断点是否在三角形中(三角形的有向积计算)
    扩展欧几里德
    UVA 116 Unidirectional TSP (白书dp)
  • 原文地址:https://www.cnblogs.com/lzxulxy/p/12491844.html
Copyright © 2020-2023  润新知