• redis的应用


    一.分布式锁

    可以保证操作的原子性

    1.简易版

    使用set key ex 5 nx value,加锁之后如果处理时间太长,锁会自动释放,可能会被下一个线程占用。

    可重入性值得是线程在持有锁的情况下再次请求加锁,可以通过ThreadLocal存储当前线程池有的锁的次数

    2.Redisson

    功能强大:

    • 可重入,使用ThreadLocal存储的重入次数
    • 公平锁,会按照加锁的顺序获取锁
    • 支持锁的到期自动续约,每1/3的国旗时间调用一次,剩余1/3过期时间自动雪月;宕机的话就不自动续约了,释放锁的时候活删除键
    • 支持阻塞式获取锁
    • 释放锁的时候会检查线程是否持有锁,避免死锁

    二.延时队列

    1.异步消息队列

    • lpush,rpush

    • blpop,brpop

      队列为空时会进入休眠状态,有数据时会立即醒过来,但是闲置过久,服务器会主动断开链接,减少资源占用,因此需要捕获异常,进行重试

    2.加锁冲突失败处理

    • 直接抛出异常,稍后重试
    • sleep一会再重试
    • 将请求转至延时队列,过一会再重试

    3.zset实现延迟队列

    • 使用zset实现延时队列,将消息序列化为一个字符串,作为value,消息的到期时间作为:当前时间+过期时间

    • 使用多个线程轮询zset获取到期的定时任务,使用zrangebyscore获取,如果获取为空则sleep之后继续获取

    三.位图

    统计365天的签到记录

    1.基本命令

    • setbit

    • getbit

    • bitcount,可以统计1/0的个数

    • bitpos ,定位第一个0/1的位置

    • bitfield,批量对指定位进行处理

      bitfield key set u8 8 97

      从第8位开始,将接下来的8个位用无符号数97代替

      • set
      • get
      • incrby
        • overflow sat,饱和溢出,停留在最大/最小值
        • overflow fail,溢出失败不执行

    四.HyperLogLog

    统计UV数,误差率0.81%,数量达到阈值后会固定占据12K的空间

    1.基本命令

    • pfadd
    • pfcount
    • pfmerge,合并多个pf

    2.实现原理

    使用多个桶,将数据分布到不同的桶中,然后甲醛平均低位连续0的个数,用以估计数据量

    五.布隆过滤器

    用来处理大数据量情况下的是否存在的问题,有一定的误判率。如爬虫对URL的去重;垃圾邮件的过滤

    1.基本命令

    • bf.add, bf.madd
    • Bf.exists, bf.mexists

    2.实现

    实际是一个大型的位数组和几个不一样的无偏hash(hash值计算的比较均匀),添加元素时根据key计算hash值,然后按照数组长度取模获取一个位置,然后其他的hash函数也都计算出来位置,将这几个位置都置为1就完成了add操作

    3…误判

    返回结果是不存在,那么一定是不存在;返回结果是存在,那么可能不存在,影响因素

    • initial_size,预估元素个数,超过时误判率会升高,默认100
    • error_rate, 错误率,越低需要的空间越大,默认0.01

    六.简单限流

    系统处理能力有限,阻止计划外的请求继续施压。

    1.实现

    值设定:

    • key:userId + 时/分/秒
    • value:timestamp
    • score:timestamp

    操作步骤:

    • add
    • zrangebyscore
    • zcard
    • expire

    2.缺点

    • 实现复杂
    • 性能不高

    七.漏斗限流

    漏斗的剩余容量代表当前行为可持续进行的操作数量,漏斗的流水速率代表该系统允许行为的最大速率。

    1.实现

    每次流水前都会灌水,更具间隙事件和流水速率计算剩余空间,能腾出多少空间取决于过去留了多少水,空间占用是一个常量,但是该方案不具有原子性

    2.可以通过redis-cells组件实现

    cl.throttle key 15 30 60,参数分别代表:

    • 15:漏斗容量,初始容量
    • 30 60: 60s允许30次操作

    返回值(按顺序):

    • 允许/拒绝
    • 容量
    • 剩余空间
    • 等待时间
    • 完全放空等待时间

    八.GeoHash

    将地图经纬度坐标映射到一维,通过zset进行维护,将score还原成坐标值就可以得到元素的原始坐标。

    1.基本命令

    • geoadd添加

      geoadd company 11 22 juejin

    • geodist计算距离

      geodist company juejin xiaomi km(m,km,ml,ft)

    • geopos、geohash获取位置

      • geopos company juejin:返回经纬度

      • geohash company juejin:返回经纬度的base32编码

    • georadiusbymember获取附件

      georadiusbymember company ireader 20 km count 3 asc

    2.数据量大时建议按照地区进行划分(国家、省、市)

    九.scan

    扫描全局key值

    1.keys

    支持模式匹配,一次遍历全部数据

    2.scan

    scan 0 match key99* count 100

    参数:

    • cursor:游标,全局hash数组的下标,为0代表遍历结束

    • key的匹配模式

    • 遍历的limit hint,是遍历的卡槽数量,而不是返回的元素个数

    遍历顺序:

    高位加法,是由rehash的规则导致的,rehash时会将下标为xxx的数据rehash到0xxx和1xxx,而采用高位加法刚好可以顺序遍历到,同时rehash时会遍历新旧两个字典结构汇总返回数据

    大key扫描:

    redis-cli -h 127.0.0.1 -p --bigkey -i 0.1每隔100条就会休眠0.1秒,避免ops剧烈抬升,但是扫描时间会变长

  • 相关阅读:
    【Java】B站课程《基于分布式架构项目实战》学习总结
    JavaScript中的模块化编程,包括CommonJS和ES6模块的区别。
    零基础想自学编程,不知道学前端还是后端还是其他,也不知道学哪种编程语言?
    nacos源码编译打包
    [附源码]java毕业设计疫情防控期间网上教学管理
    2022年竞赛打榜,神经网络还是干不过树模型??
    EasyCVR视频汇聚平台无法自动播放视频的原因排查与解决
    golang学习笔记01——基本数据类型
    面向嵌入式系统设计师的多核技术培训
    搓一个Pythonic list
  • 原文地址:https://blog.csdn.net/qq_43216019/article/details/133874287