• 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

  • 相关阅读:
    Java对MongoDB的CRUD
    MongoDB数据库基本用法
    MySQL order by 排序结果不正确
    Linux shell 脚本 eq,ne,le,ge,lt,gt意义
    Linux shell 命令运行符 &,;,&& 区别
    Linux netstat 命令详解
    Linux ss 命令详解
    Linux sort 命令详解
    Linux sed 命令详解
    Linux xargs 命令详解
  • 原文地址:https://www.cnblogs.com/itlihao/p/14969705.html
Copyright © 2020-2023  润新知