zoukankan      html  css  js  c++  java
  • Redis:高级特性和底层工作原理

    高级特性

    简单消息队列

    可以用list的rpush+lpop实现简单的消息队列功能(用blpop可以阻塞连接直到有消息时才返回)

    发布订阅模式

    消费者通过subscribe订阅一个频道,生产者通过publish发布消息到频道,实现多条发布。
    通过unsubscribe取消订阅。
    订阅的频道可以用通配符,比如(*)。

    Redis事务

    事务:保证指令一次性执行,和传统事务的区别是假如执行了,中途有错误也无法回滚(语法错误例外,语法错误会导致都不能执行)
    指令

    • MULTI:开启事务(不能嵌套)
    • EXEC:执行事务
    • DISCARD:中途放弃事务的执行
    • WATCH:类似乐观锁的实现,监视一个KEY,假如KEY的值中途有修改,会阻止这个事务的执行
    • UNWATCH
      多条命令一次性执行,只保证执行的"原子性"
    Lua脚本

    好处

    • 一次发送多个命令,减少网络开销
    • 原子性
    • lua file 实现命令集的复用

    使用

    • redis中调用脚本:eval script (参数key) (参数value)
    • lua脚本中执行redis:redis.call(command, key [param1, param2...]),command是命令,key是键,param代表给key的参数
    • 设置lua脚本命令执行超时时间,避免出现意想不到的bug(redis是单线程的),但是超时以后也是只接受不执行,为了保证原子性,这时候需要执行script kill命令,但是假如脚本中已经有数据变更了,执行script kill命令也杀不掉。这时候只能shutdown了。。。。。所以使用lua脚本要注意脚本的稳健性。

    案例
    限流令牌桶

    Redis为什么这么快

    1、纯内存操作,KV结构(时间复杂度O1)
    2、单线程:没有创建、销毁线程的开销,也不需要上下文的切换
    3、多路复用I/O
    为什么不用多线程?Redis的瓶颈在于内存,用多线程会提高复杂度,所以使用了单线程。

    虚拟内存
    • 物理内存共享出现不安全的问题,使用空间有限
    • 使用虚拟内存可以提高使用空间,划分用户使用空间
    用户空间user space和内核空间kernel space
    • 内核态:进程运行在内核空间
    • 用户态:进程运行在用户空间
    上下文切换

    CPU分时间片运行时,需要保存程序计数器等信息,然后切换,就叫上下文切换,比较耗资源。

    多路复用I/O

    传统I/O阻塞

    非阻塞I/O(NIO)少了准备数据的阻塞过程,等待数据准备过程中是非阻塞的。
    异步I/O(AIO)少了自己主动拷贝数据的过程,拷贝过程中也是非阻塞的。

    多路复用I/O:服务端会和多个客户端socket连接,使用轮询的方式轮询访问socket,任意一个socket的数据准备好了都执行读取该socket的数据。使得一个进程可以快速的保持多个连接,优点是连接多。

    Redis的过期策略

    定时过期:每个key创建一个定时器,但是key很多的时候定时器很多。
    惰性过期:下次访问key的时候,判断key是否已过期,过期则删除。(对内存不友好,过期的还在占用内存)
    set memory到达上限时,调用activeExpireCycle()释放内存
    定期过期:每次扫描一定数量,采样删除。

    redis中使用了惰性过期(访问键)和定期过期(一定时间扫描)。

    全都没有过期时间怎么办

    淘汰策略

    • allkeys-lru 最近最少使用

    • allkeys-random

    • (exception)noeviction 不淘汰

    • allkeys-lfu 一段时间内使用最少

    • volatile-lfu 一段时间内使用最少 (只针对ttl)

    • volatile-lru

    • volatile-ttl 把最快过期的删除

    • volatile-random

    • lru算法通过对象里使用一个缓存的lru时间戳来比较,当前缓存时间与对象lru时间戳距离越久,说明热度越低。

    • lfu算法和lru同一个字段,分位统计,高16位记录访问时间,低8位记录访问频率

    持久化机制

    RDB redis database

    默认的持久化方案,生成快照dump.rdb到磁盘中,重启时根据该文件恢复,
    触发机制:save seconds changes
    save 900 1
    save 300 10
    save 60 10000

    手动触发:save命令(会阻塞),redis自身是异步持久化数据,bgsave,fork子进程生成快照,并替换原来的rdb文件。

    • 优点:恢复速度快;rdb文件紧凑,适合备份
    • 缺点:有一定延迟,不能非常精准的备份。
    AOF append only file

    默认不开启,需要通过配置开启
    保存操作指令,也有触发机制:appendfsync
    appendfsync always(每次操作都存储)
    appendfsync everysecond(每秒同步一次,最常用
    appendfsync no(由系统自行决定什么时候同步)
    文件特别大时可以通过rewrite指令压缩,bgrewriteaof,系统根据配置参数(上次重写比例和最小大小)来重写。
    重写的时候假如有新指令过来会缓存新指令,AOF重写结束后将缓存命令追加到AOF里面中。

    • 优点:安全性高
    • 缺点:恢复速度慢

    同时有AOF和RDB的时候恢复会优先用AOF。

  • 相关阅读:
    正则表达式
    iOS获取设备型号、设备类型等信息
    Dubbo-Zookeeper安装
    CentOS-常用安装
    多线程-线程通信
    JVM-高效并发
    静态代理与JDK动态代理
    JVM-类加载机制
    RPC原理及实现
    JVM-自动内存管理机制
  • 原文地址:https://www.cnblogs.com/fcb-it/p/13332710.html
Copyright © 2011-2022 走看看