欢迎投稿

今日深度:

redis hash(k-value(kv)),redisk-value

redis hash(k-value(kv)),redisk-value


原文链接
为什么说reids中的哈希结构是key-value
而value又是一个key-vlaue键值对的存在呢?

我们简单举个实例来描述下Hash的应用场景,比如我们要存储一个用户信息表数据,包含以下信息:

用户ID为查找的key,存储的value用户对象包含姓名,年龄,生日等信息,如果用普通的key/value结构来存储,主要有以下2种存储方式:

第一种方式将用户ID作为查找key,把其他信息封装成一个对象以序列化的方式存储,这种方式的缺点是,增加了序列化/反序列化的开销,并且在需要修改其中一项信息时,需要把整个对象取回,并且修改操作需要对并发进行保护,引入CAS等复杂问题。

第二种方法是这个用户信息对象有多少成员就存成多少个key-value对儿,用用户ID+对应属性的名称作为唯一标识来取得对应属性的值,虽然省去了序列化开销和并发问题,但是用户ID为重复存储,如果存在大量这样的数据,内存浪费还是非常可观的。
ps一下:想想memcache这种单纯key=>value存储,你是如何做的,看看redis的解决方案

那么Redis提供的Hash很好的解决了这个问题,Redis的Hash实际是内部存储的Value为一个HashMap,并提供了直接存取这个Map成员的接口,如下图:

也就是说,Key仍然是用户ID, value是一个Map,这个Map的key是成员的属性名,value是属性值,这样对数据的修改和存取都可以直接通过其内部Map的Key(Redis里称内部Map的key为field), 也就是通过 key(用户ID) + field(属性标签) 就可以操作对应属性数据了,既不需要重复存储数据,也不会带来序列化和并发修改控制的问题。很好的解决了问题。

这里同时需要注意,Redis提供了接口(hgetall)可以直接取到全部的属性数据,但是如果内部Map的成员很多,那么涉及到遍历整个内部Map的操作,由于Redis单线程模型的缘故,这个遍历操作可能会比较耗时,而另其它客户端的请求完全不响应,这点需要格外注意。[关于这点,以后我会对大表进行验证分析]

上面已经说到Redis Hash对应Value内部实际就是一个HashMap,实际这里会有2种不同实现,这个Hash的成员比较少时Redis为了节省内存会采用类似一维数组(zipmap又称smallhash)的方式来紧凑存储,而不会采用真正的HashMap结构,对应的value redisObject的encoding为zipmap,当fields或者value增大时会自动转成真正的HashMap,此时encoding为ht。这种限制可在配置文件中配置。

实战hash类型
以下以类似用户信息表为例的操作,用户信息表主要有这三个属性 name age birthday。(当然有人要说有问题了,得到生日,不就能算出年龄了吗?我的考虑主要是测试。)

以下的命令具体用法均不详细介绍了,看一遍大约都会了

hset命令(HSET key field value)【可以看到与string不同的是多了一个fields】

    redis 127.0.0.1:6379> hset user1 name 'yueyue'
    (integer) 1
    redis 127.0.0.1:6379> hset user1 age '22'
    (integer) 1
    redis 127.0.0.1:6379> hset user1 birthday '19901222'
    (integer) 1

上面的感觉是不是太麻烦了,ok,hmset help you !!!!
hmset命令 (HMSET key field value [field value …])

redis 127.0.0.1:6379> hmset user2 name ‘zhan’ age ‘33’ birthday ‘19701322’
OK
redis 127.0.0.1:6379> hmset user3 name ‘sanli’ age ‘12’ birthday ‘20001222’
OK
既然设置了,那么我么总要查看吧,ok,查看的东西有点多,看官慢慢看来

hgetall命令(HGETALL key)

    redis 127.0.0.1:6379> hgetall user3
    1) "name"
    2) "sanli"
    3) "age"
    4) "12"
    5) "birthday"
    6) "20001222"
    redis 127.0.0.1:6379> hgetall user2
    1) "name"
    2) "zhan"
    3) "age"
    4) "33"
    5) "birthday"
    6) "19701322"

hgetall命令给出了整个信息,其实又可分解成两部分hkeys(这个hkeys是对就kye的所有fields)和hvals

hkeys命令(HKEYS key)

    redis 127.0.0.1:6379> hkeys user3
    1) "name"
    2) "age"
    3) "birthday"
    redis 127.0.0.1:6379> hkeys user2
    1) "name"
    2) "age"
    3) "birthday"
    hvals命令(HVALS key)

    redis 127.0.0.1:6379> hvals user2
    1) "zhan"
    2) "33"
    3) "19701322"
    redis 127.0.0.1:6379> hvals user3
    1) "sanli"
    2) "12"
    3) "20001222"

ok,看到上面的都是针对整个key的记录行。但如果我只想获取到user1的姓名呢?

hget命令(HGET key field)

    redis 127.0.0.1:6379> hget user1 name
    "yueyue"
    redis 127.0.0.1:6379> hget user1 age
    "22"

hmset命令(HMGET key field [field …]) 一次性获取一个key的多个fields

    redis 127.0.0.1:6379> hmget user1 age name sex nofield
    1) "22"
    2) "yueyue"
    3) "1"
    4) (nil)

一些别的相关hash命令

hincrby命令(HINCRBY key field increment)

把user1的age加上10看看

    redis 127.0.0.1:6379> hget user1 age
    "22"
    redis 127.0.0.1:6379> hincrby user1 age 10
    (integer) 32
    redis 127.0.0.1:6379> hget user1 age
    "32"

判断user1是否有qq这个属性,是否有姓名这个属性

    hexists命令(HEXISTS key field)

    redis 127.0.0.1:6379> hexists user1 name
    (integer) 1
    redis 127.0.0.1:6379> hexists user1 qq
    (integer) 0

判断user3总共有多少个fields字段

hlen命令(HLEN key)

    redis 127.0.0.1:6379> hlen user3
    (integer) 3

hdel命令(DEL key [key …])[官方上是这样写的,我更多的觉得是del key field]

    redis 127.0.0.1:6379> DEl user3 name
    (integer) 1

del命令(删除整个key)

    redis 127.0.0.1:6379> del user2
    (integer) 1
    redis 127.0.0.1:6379> hgetall user2
    (empty list or set)

redis的hash一定要弄懂哦,以后会介绍关于redis hash的一些相关应用。超越memcache,尽在redis hash应用。

www.htsjk.Com true http://www.htsjk.com/redis/35847.html NewsArticle redis hash(k-value(kv)),redisk-value 原文链接 为什么说reids中的哈希结构是key-value 而value又是一个key-vlaue键值对的存在呢? 我们简单举个实例来描述下Hash的应用场景,比如我们要存储一个用...
相关文章
    暂无相关文章
评论暂时关闭