redis 5种数据结构适用场景

网上介绍太笼统了,呕心沥血整理出来的可理解的适用场景,查看下图

redis-cli指令大全:点击查看redis指令

Redis支持5种数据类型:

  1. string(字符串)

  1. hash(哈希)

  1. list(列表)

  1. set(集合)

  1. zset(sorted set:有序集合)

string是 redis 最基本的类型,一个 key 对应一个 value。value其实不仅是String,也可以是数字。

使用场景:常规key-value缓存应用。常规计数(incr): 微博数, 粉丝数,点赞数等

常用命令set,get incr,incrby,decrby,del


hash 是一个键值(key => value)对集合。特别适合存储对象。

要存储一个用户信息对象数据,包含以下信息:

用户ID为查找的key,存储的value用户对象包含姓名,年龄,生日等信息,如果用普通的key/value结构来存储,

通常我们会选择以下两种方式:

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

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

常用命令:

hset,hget,mset , mget

books对象 name ,page,monty作为属性和key

hset,hget适用于属性信息存储,mset,mget 一次设置多个key

hash是否可以单独修改指定属性呢?可以的,直接再次存储即可

如何快速删除key呢?

hgetall取出来的数据结构是什么,怎么取数据?map[string]string

func HsetGet(conn redis.Conn){
    key := "abc"
    _, err := conn.Do("hset", "books", key, "1") //books是哈希表名 其中存的是一条条key-value
    if err != nil {
        fmt.Printf("set failed:%s", err)
        return
    }
    _, err = conn.Do("hset", "books", "efg", "2") //books是哈希表名 其中存的是一条条key-value
    if err != nil {
        fmt.Printf("-----set failed:%s", err)
        return
    }
    // 取单个值
    data, err := redis.String(conn.Do("hget", "books", key)) //books是哈希表名 其中存的是一条条key-value
    if err != nil {
        fmt.Printf("get failed, err:%v", err)
        return
    }
    fmt.Printf("HsetGet key:%s value:%s \n", key, data)
    // 取全部值
    all, err := redis.StringMap(conn.Do("hgetall", "books")) //books是哈希表名 其中存的是一条条key-value
    if err != nil {
        fmt.Printf("get failed, err:%v", err)
        return
    }
    fmt.Println("all.abc ",all["abc"])

    allByte ,_:= json.Marshal(all)
    fmt.Println(string(allByte))
    var result = make(map[string]string,0)
    json.Unmarshal(allByte,&result)
    fmt.Println(result["page"])
    for k,v := range result {
        fmt.Println("k:",k,"v:",v)
    }
    redis.StringMap(conn.Do("del", "books"))  // 删除key

}

list列表是简单的字符串列表,按照插入顺序排序。

应用场景:Redis list的应用场景非常多,也是Redis最重要的数据结构之一,比如twitter的关注列表,粉丝列表等都可以用Redis的list结构来实现,通过lpush往列表里插入新元素,然后通过lrange命令读取最新元素列表,如朋友圈点赞、评论列表。

点对点的简单消息队列应用(lpop 和lpush 实现)

定时计算的排行榜,lrage可以用取数据。非定时的话,数据会多一些需要排序。

常用指令:lpush:左入队,lpop

如何一次性取出所有数据?如何删除数据?

用lrange取出,数据结构是数组

del key即可删除list列表

import (
    "encoding/json"
    "runtime"
    "testing"
    "time"
    //"github.com/go-redis/redis"  这个包是首选
    "github.com/garyburd/redigo/redis"
    "fmt"
)

func  main(){
db := &redis.Pool{
        MaxIdle:     1,
        MaxActive:   3,
        IdleTimeout: 4 * time.Second,
        Dial: func() (redis.Conn, error) {
            c, err := redis.DialURL("redis://192.168.1.201:6379/10")
            if err != nil {
                fmt.Printf("redis connection error: %v \n", err)
                return nil, fmt.Errorf("redis connection error: %s", err)
            }
            return c, err
        },
        TestOnBorrow: func(c redis.Conn, t time.Time) error {
            _, err := c.Do("PING")
            if err != nil {
                fmt.Printf("ping redis error: %v \n", err)
                return fmt.Errorf("ping redis error: %v", err)
            }
            return nil
        },
    }
    c := db.Get()
    defer c.Close()
     List(c)
}

func List(conn redis.Conn){
    _, err := conn.Do("del", "book_stack" ) //左边进 第二个参数book_lsit是队列名
    if err != nil {
        fmt.Printf("del set failed:%s \n", err)
        return
    }

    _, err = conn.Do("lpush", "book_stack", 1, 2,3,4,5) //左边进 第二个参数book_lsit是队列名
    if err != nil {
        fmt.Printf("List set failed:%s \n", err)
        return
    }

    data, err := redis.String(conn.Do("lpop", "book_stack")) //左边出,一次只能出队一个元素
    if err != nil {
        fmt.Printf("List get failed, err:%v \n", err)
        return
    }
    fmt.Printf("data  value:%s \n", data)
    lrange, err := redis.Int64s(conn.Do("lrange", "book_stack", 0,-1) )//左边出,一次只能出队一个元素
    if err != nil {
        fmt.Printf("List get failed, err:%v \n", err)
        return
    }
    for k,v := range lrange {
        fmt.Println("k:",k,"v:",v)
    }
    fmt.Printf("lrange  value:%v \n", lrange)
}

set是string类型的无序不重合集合。 set 数据有序?纯数字的一般是有序的,其他的确实是无序,所以整体是无序。数据类型是interface,可以同时添加不同类型数据

127.0.0.1:6379[10]> sadd gg 20 200 60 600 qq oo pp aa ss
(integer) 4
127.0.0.1:6379[10]> smembers gg
1) "3"
2) "20"
3) "200"
4) "2"
5) "oo"
6) "pp"
7) "qq"
8) "ss"
9) "4"
10) "60"
11) "aa"
12) "600"
13) "1"

集合是通过hashtable实现的,概念和数学中个的集合基本类似,可以交集,并集,差集等等,set中的元素是没有顺序的。所以添加,删除,查找的复杂度都是O(1)。

常用命令: sadd(添加多个),smembers(获取数据),scard(元素数量),srem(移除一个或多个元素),Sismember (判断成员元素是否是集合的成员),Sscan (命令用于迭代集合键中的元素)。

Sinter 命令返回给定所有给定集合的交集。 不存在的集合 key 被视为空集。 当给定集合当中有一个空集时,结果也为空集(根据集合运算定律)。 sinter key1 ke2 ...

如何直接判断元素在set集合内是否存在?而不是遍历去查看

sismember key xxx(元素)

场景:用户关注的人,用户的粉丝,共同好友,共同关注,共同爱好,微信抽奖小程序

微信微博点赞,收藏、标签。详细的使用快点这里呀 点击查看呀

更多指令参考这里:点击查看redis指令


zset和 set 一样也是string类型元素的集合,且不允许重复的成员。 *zadd 命令:*添加元素到集合,元素在集合中存在则更新对应score。 常用命令:zadd,zrange,zrem,zcard等

不同的是每个元素都会关联一个double类型的分数。Redis正是通过分数来为集合中的成员进行从小到大的排序。zset的成员是唯一的,但分数(score)却可以重复。

使用场景:Redis sorted set的使用场景与set类似,区别是set不是自动有序的,而sorted set可以通过用户额外提供一个优先级(score)的参数来为成员排序,并且是插入有序的,即自动排序。

使用场景:微信步数排行榜、玩家游戏排行榜、成绩单排名。

更多使用场景,查看这里,真的很详细。https://www.jianshu.com/p/f00128af8dbf

go redis相关使用代码示例,跳转这里

参考链接:

https://blog.csdn.net/ckckckcckckc/article/details/127727334

http://t.zoukankan.com/forever521Lee-p-9494951.html

redis高可用方案

https://www.jianshu.com/p/7d5fbf90bcd7

https://www.jianshu.com/p/f439da2b2d2d 哨兵模式详解

猜你喜欢

转载自blog.csdn.net/xia_2017/article/details/128618821