[Redis][Hash]详细讲解

打印 上一主题 下一主题

主题 1036|帖子 1036|积分 3108


0.前言



  • 在Redis中,哈希范例是指值本⾝是⼀个键值对布局,形如key="key",value={{field1, value1}, ..., {fieldN, valueN}}
  • 字符串和哈希范例对比:存储一个uid为1的用户对象,姓名James,年龄28

  • 留意:哈希范例中的映射关系通常称为field-value,⽤于区分Redis整体的键值对(key-value), 留意这⾥的value是指field对应的值,不是键(key)对应的值

1.常见下令

1.HSET



  • 功能:设置hash中指定的字段(field)的值(value)
  • 语法:`HSET key field value [field value]
  • 返回值:添加字段的个数
  • 时间复杂度:插入一组field为                                        O                            (                            1                            )                                  O(1)                     O(1),插入N组field为                                        O                            (                            N                            )                                  O(N)                     O(N)

2.HGET



  • 功能:获取hash中指定字段的值
  • 语法:HGET key field
  • 返回值:字段对应的值大概nil
  • 时间复杂度:                                        O                            (                            1                            )                                  O(1)                     O(1)

3.HEXISTS



  • 功能:判断hash中是否有指定的字段
  • 语法:HEXISTS key field
  • 返回值:1表现存在,0表现不存在

4.HDEL



  • 功能:删除hash中指定的字段
  • 语法:HDEL key field [field ...]
  • 返回值:本次操作删除的字段个数
  • 时间复杂度:删除一个元素为                                        O                            (                            1                            )                                  O(1)                     O(1),删除N个元素为                                        O                            (                            N                            )                                  O(N)                     O(N)

5.HKEYS



  • 功能:获取hash中的全部字段

    • 先根据key找到对应的hash ->                                                   O                                  (                                  1                                  )                                          O(1)                           O(1)
    • 然后再遍历hash ->                                                   O                                  (                                  N                                  )                                          O(N)                           O(N)

  • 语法:HKEYS key
  • 返回值:字段列表
  • 时间复杂度:                                        O                            (                            N                            )                                  O(N)                     O(N),N为field的个数
  • 留意:该操作也是存在一定风险的,雷同于之前先容的KEYS

6.HVALS



  • 功能:获取hash中全部的值
  • 语法:HVALS key
  • 返回值:全部的值
  • 时间复杂度:                                        O                            (                            N                            )                                  O(N)                     O(N),N为field的个数

7.HGETALL



  • 功能:获取hash中的全部字段以及对应的值
  • 语法:HGETALL key
  • 返回值:字段和对应的值
  • 时间复杂度:                                        O                            (                            N                            )                                  O(N)                     O(N),N为field的个数
  • 留意:在使⽤HGETALL时,假如哈希元素个数⽐较多,会存在阻塞Redis的大概

    • 假如只需要获取部分field,可以使⽤HMGET
    • 假如⼀定要获取全部field,可以尝试使⽤HSCAN下令,该下令采⽤渐进式遍历哈希范例


8.HMGET



  • 功能:一次获取hash中多个字段的值
  • 语法:HMGET key field [field ...]
  • 返回值:字段对应的值大概nil
  • 时间复杂度:只查询⼀个元素为                                        O                            (                            1                            )                                  O(1)                     O(1),查询多个元素为                                        O                            (                            N                            )                                  O(N)                     O(N),N为查询元素个数

9.HLEN



  • 功能:获取hash中的全部字段的个数
  • 语法:HLEN key
  • 返回值:字段个数
  • 时间复杂度:                                        O                            (                            1                            )                                  O(1)                     O(1)

10.HSETNX



  • 功能:在字段不存在的环境下,设置hash中的字段和值
  • 语法:HSETNX key field value
  • 返回值:1表现设置乐成,0表现失败
  • 时间复杂度:                                        O                            (                            1                            )                                  O(1)                     O(1)

11.HINCRBY



  • 功能:将hash中字段对应的数值添加指定的值
  • 语法:HINCRBY key field increment
  • 返回值:该字段变革之后的值
  • 时间复杂度:                                        O                            (                            1                            )                                  O(1)                     O(1)

12.HINCRBYFLOAT



  • 功能:HINCRBY的浮点数版本
  • 语法:HINCRBYFLOAT key field increment
  • 返回值:该字段变革之后的值
  • 时间复杂度:                                        O                            (                            1                            )                                  O(1)                     O(1)

2.内部编码

1.ziplist(压缩链表)



  • 当哈希范例元素个数⼩于hash-max-ziplist-entries设置(默认512个)、 同时全部值都⼩于hash-max-ziplist-value设置(默认64字节)时,Redis会使⽤ziplist作为哈希的内部实现
  • ziplist使⽤更加紧凑的布局实现多个元素的连续存储,以是在节省内存⽅⾯⽐hashtable更加优秀

2.hashtable(哈希表)



  • 当哈希范例⽆法满⾜ziplist的条件时,Redis会使⽤hashtable作为哈希的内部实现,由于此时ziplist的读写服从会下降,⽽hashtable的读写时间复杂度为O(1)
  • 哈希范例的内部编码,以及响应的变革

    • 当field个数⽐较少且没有⼤的value时,内部编码为ziplist
    • 当有value⼤于64字节时,内部编码会转换为hashtable
    • 当field个数超过512时,内部编码也会转换为hashtable


3.利用场景



  • 关系型数据表记录的两条用户信息

  • 映射关系表⽰⽤⼾信息:可以将每个⽤⼾的id定义为键后缀,多对field-value对应⽤⼾的各个属性

  • 优势:相⽐于使⽤JSON格式的字符串缓存⽤⼾信息,哈希范例变得更加直观,并且在更新操作上变得更灵活
    1. UserInfo GetUserInfo(long uid)
    2. {
    3.         // 根据 uid 得到 Redis 的键
    4.         String key = “user:" + uid;
    5.         // 尝试从 Redis 中获取对应的值
    6.         userInfoMap = Redis 执⾏命令: hgetall key;
    7.         // 如果缓存命中(hit)
    8.         if (value != null)
    9.         {
    10.                 // 将映射关系还原为对象形式
    11.                 UserInfo userInfo = 利⽤映射关系构建对象 (userInfoMap);
    12.                 return userInfo;
    13.         }
    14.         // 如果缓存未命中(miss),从数据库中,根据 uid 获取⽤⼾信息
    15.         UserInfo userInfo = MySQL 执⾏ SQL :
    16.                                                 select * from user_info where uid = <uid>
    17.         // 如果表中没有 uid 对应的用户信息
    18.         if (userInfo == null)
    19.         {
    20.                 响应404
    21.                 return null;
    22.         }
    23.         // 将缓存以哈希类型保存
    24.         Redis 执⾏命令:
    25.                 hmset key name userInfo.name age userInfo.age city userInfo.city
    26.         // 写⼊缓存,为了防⽌数据腐烂(rot),设置过期时间为 1 ⼩时
    27.         Redis 执⾏命令: expire key 3600
    28.         // 返回用户信息
    29.         return userInfo;
    30. }
    复制代码
  • 需要留意的是哈希范例和关系型数据库有两点不同之处

    • 哈希范例是稀疏的,⽽关系型数据库是完全布局化的

      • 比方:哈希范例每个键可以有不同的field,⽽关系型数据库⼀旦添加新的列,全部⾏都要为其设置值,纵然为null


    • 关系数据库可以做复杂的关系查询,⽽Redis去模拟关系型复杂查询

      • 比方:联表查询、聚合查询等根本不大概,维护成本⾼



4.缓存方式对比



  • 现在学习了三种方法缓存用户信息,以下给出三种方案的实现方法和优缺点分析
1.原⽣字符串范例



  • 说明:使⽤字符串范例,每个属性⼀个键
  • 优点:实现简单,针对个别属性变更也很灵活
  • 缺点:占⽤过多的键,内存占⽤量较⼤,同时⽤⼾信息在Redis中⽐较分散,缺少内聚性,以是这种⽅案根本没有实⽤性
  • 示例
    1. set user:1:name James
    2. set user:1:age 23
    3. set user:1:city Beijing
    复制代码

2.序列化字符串范例



  • 说明:比方JSON格式
  • 优点:针对总是以整体作为操作的信息⽐较合适,编程也简单。同时,假如序列化⽅案选择合适,内存的使⽤服从很⾼
  • 缺点:本⾝序列化和反序列需要⼀定开销,同时假如总是操作个别属性则⾮常不灵活
  • 示例:set user:1 经过序列化后的⽤⼾对象字符串

3.哈希范例



  • 优点:简单、直观、灵活,尤其是针对信息的局部变更大概获取操作
  • 缺点:需要控制哈希在ziplist和hashtable两种内部编码的转换,大概会造成内存的较⼤斲丧

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

莫张周刘王

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表