美文网首页
Redis的一些进阶使用技巧

Redis的一些进阶使用技巧

作者: gao922699 | 来源:发表于2022-08-22 09:23 被阅读0次

    分布式锁

    主要原理:利用setnx命令占坑

    核心命令:set lock_codehole true ex 5 nx

    http://zhangtielei.com/posts/blog-redlock-reasoning.html

    官方的分布式锁实现:redlock算法 https://redis.io/topics/distlock 这里有php的实现

    hyperLogLog

    功能类似set,但是他只提供计数功能,而且去重有一定误差(百分之零点几),优点是占用空间小(固定的12K)

    适合存储数量很大但是对去重精确性要求不高的数据(比如网站UV值)

    PFADD,PFCOUNT,PFMERGE三个命令

    布隆过滤器

    上面的hyperLogLog只提供计数,没有查值的功能。布隆过滤器可以判断值是否存在。

    简化的set,有一定误差

    是一个插件,可以通过docker安装:docker pull redislabs/rebloom

    命令:bf.add,bf.exists,bf.madd,bf.mexists

    充分利用上述结构(包括set)的去重特性很重要

    例:爬虫中url的去重

    限流策略

    https://www.jianshu.com/p/d44a63bce187

    geohash地理位置距离排序

    geohash是一种通用的地理算法,mysql、mongodb等也有对应的支持,有空可以研究一下。

    https://www.jianshu.com/p/a48eec659952

    scan和keys对比

    复杂度虽然也是 O(n),但是它是通过游标分步进行的,不会阻塞线程;

    提供 limit 参数,可以控制每次返回结果的最大条数,limit 只是一个 hint,返回的结果可多可少;

    同 keys 一样,它也提供模式匹配功能;

    服务器不需要为游标保存状态,游标的唯一状态就是 scan 返回给客户端的游标整数;

    返回的结果可能会有重复,需要客户端去重复,这点非常重要;

    遍历的过程中如果有数据修改,改动后的数据能不能遍历到是不确定的;

    单次返回的结果是空的并不意味着遍历结束,而要看返回的游标值是否为零;

    scan 0 match test_* count 1000

    1. "13976"

      1. "test_12"

      2. "test_33"

      3. "test_534"

    注意点:

    0代表游标位置,从0开始。scan会返回结束游标位置,如果不是0,应该从这个位置继续扫描。0代表扫描完毕,比如上面的返回结果是13976,下一条scan指令应该是:scan 13976 match test_* count 1000;

    这个count不是取出元素的个数,而是一次scan的字典槽位数量,可能limit1000获取到的元素个数值有10个;

    zscan、hscan、sscan等可以遍历指定集合内的元素。

    数据持久化

    快照:全量备份,把内存中的数据存储到磁盘上

    AOF:增量备份,把执行的指令记录下来

    为什么redis不适合做数据库,只适合做缓存?

    1.成本-首先成本原因,因为Redis是内存数据库,而内存相对于磁盘来说虽然性能很高,但是成本更高,在做大量数据存储时成本问题尤为突出

    2.持久性-Redis数据丢失率,上面看到不管是RDB还是AOF都会进行IO操作,那么在持久化过程为了提高性能就需要降低保存频率,那么必然会有数据丢失的情况,无法保证数据的完整性

    3.查询特性-Redis的数据特性导致查询功能特性较少,而数据库一般需要支持多样查询,redis无法适用这样的场景

    4.事务特性:redis不具备事务特性,尤其是在分布式环境下尤为特出

    管道

    本质是在客户端把多个命令一次性发送、一次性接收,减少网络开销。

    laravel实现:

    Redis::pipeline(function ($pipe) {
                for ($i = 0; $i < 1000; $i++) {
                    $pipe->set("key:$i", $i);
                }
            }); // 管道操作,在一次操作插入或者读出多次
    $redis = Redis::keys("*");
    var_dump($redis);exit;
    

    事务

    multi/exec/discard对应begin/commit/rollback

    注意:

    redis事务没有原子性,比如执行了3条指令,其中一条失败了,并不会回滚所有指令,另外两条仍然会被执行。

    所以redis的事务只满足了隔离性

    watch命令

    分布式锁相当于悲观锁,watch相当于乐观锁

    > watch books
    
    OK
    
    > incr books  # 被修改了
    
    (integer) 1
    
    > multi
    
    OK
    
    > incr books
    
    QUEUED
    
    > exec  # 事务执行失败
    
    (nil)
    

    注意:

    1. exec返回nil时表示books被修改了所以事务执行失败

    2. watch要在mutil之前执行

    3. 可以用unwatch取消监事,如果执行了exec或discard会自动取消所有对key的监视

    分布式的一些东西,暂时不深入研究了,知道一些概念用到的时候再学

    主从同步

    Redis Sentinel(哨兵)主服务挂了以后自动切换到从服务

    Redis cluster 官方的redis集群

    5.0以后的新数据结构:
    Stream.用来替代pub/sub。准备另起一篇来记录stream的东西。

    相关文章

      网友评论

          本文标题:Redis的一些进阶使用技巧

          本文链接:https://www.haomeiwen.com/subject/ajoawrtx.html