zoukankan      html  css  js  c++  java
  • redis知识总结与分布式锁的实现

    1. 常用命令

    为指定key设置过期时间:expire key seconds

    设置key对应的value,并设置过期时间:setex key seconds value

    查询指定key剩余过期时间:ttl key

    返回指定key的value类型:type key

    为指定key修改key名称:rename oldkey newkey

    setnx key value:设置key和value值,若当前key不存在时,若存在则不执行该操作



    2. Redis支持的数据类型

    • string
    • hash
    • list
    • set
    • sorted set



    3. Redis的持久化机制

    Redis是一个非关系型的内存数据库,一旦redis重启或断电数据就会丢失[没有持久化的情况下]。

    持久化:将redis的数据持久化保存到硬盘上。

    Redis提供的持久化机制有如下2种:

    • RDB(默认)
    • AOF

    3.1 RDB

    RDB持久化机制是默认开启的持久化机制,一般不需要更改。它会在一定时间内检测key的变化,达到要求就会将内存种的数据集快照写入磁盘,它恢复时是将快照文件直接读取到内存里。

    RDB保存的文件时dump.rdb。

    触发机制:

    • save规则满足的情况下
    • 执行flushall命令
    • 推出redis也会






    3.2 AOF

    AOP持久化机制是以独立日志的方式记录每次写命令,并在Redis重启时重新执行AOF文件中的名称来达到恢复数据的目的。

    以独立日志的方式:指以日志形式记录每个操作,将Redis运行过程中的所有指令记录下来,redis启动之初就会读取该文件重新构建数据。

    AOF保存的是 appendonly.aof 文件。

    特点:

    • 每一次修改都同步
    • 每秒同步一次,可能会丢失一秒的数据

    开启AOP持久化机制
    将配置文件种的 appendonly 由 no 改为 yes




    4. 建议





    5. redis删除策略

    问题:redis种若有一个key只能存活1小时,那么redis是如何对这个key删除的?
    redis有3种删除策略:

    • 定期删除 每隔100秒随机抽取3个设置过期时间的key,判断其是否过期,是就删除
    • 惰性删除 若定期删除没有随机抽取到那个过期的key,也不怕,惰性删除会在你查询那个key时,先去判断其是否过期,是就删除
    • 定时删除 在设置键过期的同时,创建一个定时器,让定时器在键过期时间来临时,执行对键的删除操作。

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



    6. redis如何保存对象

    一般会将对象转换成json字符串,再将其当字符串保存。



    7. 什么是缓存穿透,缓存击穿,缓存雪崩

    7.1 缓存穿透

    缓存穿透:查询一个数据库一定不存在的数据。

    7.2 缓存击穿

    缓存击穿:指一个key非常热点,扛着大并发几种对其访问,当这个key失效的瞬间,所有请求直接请求到数据库。

    7.3 缓存雪崩

    缓存雪崩:指一段时间内,缓存集中过期。



    7. 为什么Redis是单线程的?为什么单线程还能这么快

    原文:https://www.cnblogs.com/panchanggui/p/12597920.html

    • Redis是基于内存的,内存的读写速度非常快;
    • Redis是单线程的,避免了不必要的上下文切换和竞争条件;
    • Redis使用多路复用技术,可以处理并发的连接。非阻塞I/O内部实现采用epoll,采用了epoll+自己实现的简单的事件框架。epoll中的读、写、关闭、连接都转化成了事件,然后利用epoll的多路复用特性,绝不在io上浪费一点时间。

    为什么Redis是单线程的?

    1. 官方答案
      因为Redis是基于内存的操作,CPU不是Redis的瓶颈,Redis的瓶颈最有可能是机器内存的大小或者网络带宽。既然单线程容易实现,而且CPU不会成为瓶颈,那就顺理成章地采用单线程的方案了。
    2. 性能指标
      关于Redis的性能,官方网站也有,普通笔记本轻松处理每秒几十万的请求。
    3. 详细原因

    3.1 不需要各种锁的性能消耗
    Redis的数据结构并不全是简单的Key-Value,还有list,hash等复杂的结构,这些结构有可能会进行很细粒度的操作,比如在很长的列表后面添加一个元素,在hash当中添加或者删除一个对象。
    这些操作可能就需要加非常多的锁,导致的结果是同步开销大大增加。
    总之,在单线程的情况下,就不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗。

    3.2 单线程多进程集群方案
    单线程的威力实际上非常强大,核心效率也非常高,多线程自然是可以比单线程有更高的性能上限,但是在今天的计算环境中,即使是单机多线程的上限也往往不能满足需要了,需要进一步摸索的是多服务器集群化的方案,这些方案中多线程的技术照样是用不上的。
    所以单线程、多进程的集群不失为一个时髦的解决方案。

    3.3 CPU消耗
    采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU。
    但是如果CPU成为Redis瓶颈,或者不想让服务器其他CUP核闲置,那怎么办?
    可以考虑多起几个Redis进程,Redis是key-value数据库,不是关系数据库,数据之间没有约束。只要客户端分清哪些key放在哪个Redis进程上就可以了。



    7. 什么是分布式锁,如何基于Redis实现分布式锁

    7.1 单体项目里面锁的使用

    举例:
    客户下单的时候,我们调用库存中心进行减库存,那我们一般的操作都是:

    update store set num = $num where id = $id
    

    但是,当客户量高的时候,出现了一些并发时,就容易出现脏数据问题,就像我们的经典售票案例。
    比如 a, b 当前两个事务,查询出来的库存都是 5,a 买了 3 个单子要把库存设置为 2,而 b 买了 1 个单子要把库存设置为 4,那这个时候就会出现 a 会覆盖 b 的更新。

    解决办法:
    想办法解决脏数据的问题呗,比如让a事务再修改的时候不准其他事务来修改,或者让a事务直到在它修改期间是否有其他事务来改过该数据,是就不就进行更新。

    • 乐观锁:假定不会发生数据冲突,所以获取数据的时候不加锁,但是在提交数据的时候,会判断是否被修改过,如果被修改过则不进行数据更新,如果判断没被其他线程修改,则进行数据更新。
    • 悲观锁:读取数据之前,假设会发生并发冲突,所以从一开始就为了防止冲突,在获取数据的时候进行加锁,确保自己使用的过程中不会被修改,使用完成之后在进行锁的释放。上锁期间,其他事务不能查询和修改。

    Mysql实现乐观锁:在表中加一个version字段,查询数据时得到它的值,更新时加上这个条件。
    Mysql实现悲观锁:1) 先关闭mysql的自动提交功能。2)在查询数据时加上"for update"

    线程是实现悲观锁:典型的是Synchronized,Lock锁,他们就是悲观锁的体现。

    7.2 分布式项目里面锁的使用

    在分布式系统中,由于会部署集群,一个应用部署到多台机器上,也就是多个JVM。
    如此一来基于JAVA API实现线程的方式就不行了。因为变量会在不同JVM中分配3个内存,加锁控制不了。

    那基于数据表的乐观锁或悲观锁呢,能有效不呢:
           能有效!!!
           基于JAVA API实现的锁,依赖于JVM。
           基于MYSQL实现的乐观锁,悲观锁,依赖的是Mysql。

    缺点:
           当更新的时候,数据被另一个事务修改了,则当前更新不成功。由此可以看出基于mysql的乐观锁适合多读少些的情况,并且具有一定锁表的风险。
           悲观锁就更不说了,查询的时候就直接不准其他人访问了。更不适合。

    7.3 基于redis实现分布式锁

    优点:性能对比ZK和Mysql较好。
    缺点:没有mysql实现方便,还涉及lua脚本知识点。

    几种实现分布式锁的方式对比:https://www.cnblogs.com/heyanan/p/13591217.html
    基于注解的redis实现分布式锁:https://blog.csdn.net/tianyaleixiaowu/article/details/90036180

  • 相关阅读:
    CF1202F You Are Given Some Letters...
    CF1178E Archaeology
    PTA (Advanced Level) 1005 Spell It Right
    PTA (Advanced Level) 1004 Counting Leaves
    Qt5——从零开始的Hello World教程(Qt Creator)
    PTA (Advanced Level) 1003 Emergency
    PTA (Advanced Level) 1002 A+B for Polynomials
    HDU 1272 小希的迷宫
    FZU 2150 Fire Game
    HihoCoder
  • 原文地址:https://www.cnblogs.com/itlihao/p/14969705.html
Copyright © 2011-2022 走看看