Redis学习笔记—数据类型

  1. String

    string是redis最基本的数据类型,他是二进制安全的---意味着string可以包含任何数据,jpg图片序列化对象等等。一个string的value最大可以是512M(10^6bytes)

    set key value //设置K-V,若存在则覆盖原值
    keys * //获取所有key
    setex key <过期时间> <value>
    getset <key> <value> //设置新值返回旧值
    ------
    以下均为原子命令
    incr k //v为数字是+1,下同
    incrby num //增加指定数量
    decr k //减操作
    mset k1 v1 k2 v2... //同时设置多个值
    mget k1 k2 ...
    getrange //根据范围获取值,下面是设置值
    setrange

    string的的数据结构为简单的动态字符串,是可修改的字符串。实现上类似golang的byte切片,预分配空间来减少内存的频繁分配。len < 1M时扩容是翻倍,超过后每次增加1M,注意最大长度为512M。

  2. List
    redis的list是简单的字符串列表,按照插入顺序排序,可以添加一个元素到头或者尾,底层实际是个双向链表。

    lpush/rpush key //左右放入
    lpop/rpop key //取值k也消亡
    rpoplpush key1 key2 //从k1右边取3,放入k2左边
    lrange key start end
    linsert key BEFORE|AFTER pivot element
    lrem key count element //从左边删除count数量v
    lset key index element //覆盖index的v

    List的数据结构是quicklist。在元素较少的情况下会使用一块连续内存存储,结构是ziplist,当数据较多时用多个双向指针将ziplist串起来。

    普通链表的附加指针空间太大比较浪费,上述结构可以节省空间。

  3. Set
    set是string类型的无序集合,与list类似的列表功能,不过可以自动去重(类似cpp的set)。set提供了判断某个成员是否在内的一个接口(sismemebr)这是list不具备的。底层是一个value为null的哈希表。

    sadd key member [member ...] //将一个或多个成员加入集合key
    smembers key //取出集合key全部元素
    sismember key value //判断集合key是否有value
    scard key //判断集合元素个数
    srem key v1, v2... //删除集合k中元素
    spop key //集合中随机弹出一个元素
    srandmember key n //随机取出n个值,但不会删除
    smove source destination member //把集合的一个v移动到另一集合
    sinter //取交并差集,后面的key可以是多个
    sunion
    sdiff

    set底层结构是dict字典,字典是用hash表实现的。与java的hashset类似,所有的value都指向同一个内部值。

  4. Hash

    redis hash是一个string类型的filed-value,适合存储对象类似java的Map<String,Object>

    hset key field value [field value ...] //给key中field赋值
    hmset key field value [field value ...] //批量设置hash
    hget key field //取值
    hexists key field //判断field是否存在
    hkeys key //列出所有field
    hvals key //列出所有value
    hincrby key field increment //给field对应值+1,-1
    hsetnx key field value //当field不存在设置field-value,不会覆盖

    底层实现:当F-V长度短且数量较少使用ziplist,否则使用hashtable

  5. Zset-有序集合

    在基本集合基础上给每个成员增加了score,用来增序排序,元素唯一但是score可以重复。访问Zset集合的中间成员也是很快的因此可以用来作为一个没有重复成员的只能列表。

    zadd key score1 valuel... //添加元素
    zrange key start stop [WITHSCORES] //返回指定顺序区间元素
    zreeange key start stop [WITHSCORES] //同上逆顺
    zrangebyscore key min max [WITHSCORES] //返回score区间的元素
    zrevrangebyscore key max min [WITHSCORES] //从大到小排序
    zincrby key increment member //为元素增加制定的值score
    zrem key member [member ...] //删除制定元素
    zcount key min max //统计区间内元素个数
    zrank key member //返回元素排名

    Zset底层使用了两个数据结构

    • Hash : hash用来关联元素value和score保证value唯一性,可以通过V找到S,field是value,value是score
    • 跳跃表:用来给V排序,根据score的范围获取元素列表
  6. Bitmaps
    Bitmaps本身不是一种数据类型, 实际上它就是字符串(key-value) , 但是它可以对字符串的位进行操作。 可以把Bitmaps想象成一个以位为单位的数组, 数组的每个单元只能存储0和1, 数组的下标在Bitmaps中叫做偏移量。在第一次初始化Bitmaps时, 假如偏移量非常大, 那么整个初始化过程执行会比较慢, 可能会造成Redis的阻塞

    setbit key offset value //设置Bitmaps中某个偏移量的值
    getbit key offset //获取Bitmaps中某个偏移量的值
    bitcount key [start end] [BYTE|BIT] //统计字符串从start字节到end字节比特值为1的数量
    bitop and(or/not/xor) destkey key… //位运算and,or,not,xor结果保存在destkey

    注意:redis的setbit设置或清除的是bit位置,而bitcount计算的是默认是byte位置,可选bit

    考虑如下场景:

    每个独立用户是否访问过网站存放在Bitmaps中, 将访问的用户记做1, 没有访问的用户记做0, 用偏移量作为用户的id。如果活跃用户数量非常庞大的情况下Bitmap的空间效率和set相比会高很多,尤其是随着时间推移节省的内存还是非常可观的。但是活跃用户较少的情况下Bitmap的大多数位是0则会造成很多浪费,空间利用率可能反而不如set。

  7. HyperLogLog

    独立ip数、搜索记录数等需要去重和计数这种求集合中不重复元素个数的问题称为基数问题。解决基数问题有很多种方案通常有:

    • 数据存储在MySQL表中,使用distinct count计算不重复个数

    • 使用Redis提供的hash、set、bitmaps等数据结构来处理

    以上的方案结果精确,但随着数据不断增加,导致占用空间越来越大,对于非常大的数据集是不切实际的。

    HyperLogLog的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定且很小。每个HyperLogLog 键只需要花费 12 KB内存,就可以计算接近 2^64 个不同元素的基数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。因为HyperLogLog只会根据输入元素来计算基数,而不会储存输入元素本身,所以HyperLogLog不能像集合那样,返回输入的各个元素

    pfadd <key><element> [element ...] //添加指定元素到 HyperLogLog 中
    pfcount<key> [key ...] //计算HLL的近似基数
    pfmerge<destkey><sourcekey> [sourcekey ...] //将一个或多个HLL合并后的结果存储在另一个HLL中
  8. Geospatial

    redis基于该类型,提供了经纬度设置,查询,范围查询,距离查询,经纬度Hash等常见操作。两极无法直接添加,一般会下载城市数据,直接导入

    geoadd <key><longitude><latitude><member> [longitude latitude member...] //添加地理位置(经度,纬度,名称)
    geopos <key><member> [member...] //获得指定地区的坐标值
    geodist <key><member1><member2> [m|km|ft|mi ] //获取两个位置之间的直线距离
    georadius<key>< longitude><latitude>radius m|km|ft|mi //以给定的经纬度为中心,找出某一半径内的元素
posted @   ArthurFleck  阅读(41)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
点击右上角即可分享
微信分享提示