go-Redis
基本介绍
- Redis是NoSQL数据库,不是传统的关系数据库
- Redis:REmote DIctionary Server 远程字典服务器,Redis性能非常高,单机能够达到15w qps,通常适合做缓存,也可以做持久化
- 完全开源免费的,高性能的(key/value)分布式内存数据库,基于内存运行并支持持久化的NoSQL数据库,是最热门NoSQL数据库之一,也称为数据结构服务器
终端使用
- Redis的五大数据类型:String、Hash、List、Set、zset(有序的Set)
字符串String
- string是redis最基本的类型,一个key对应 一个value
- string类型是二进制安全的。除普通的字符串外,也可以存放图片等数据
- redis中字符串value最大是512M
-
CRUD:
-
set 若存在就修改,不存在就添加
setex address1 10 beijing
设置销毁时间mset
同时设置一个或多个key-value对msetnx
同时设置多对不存在的key-value对,若有存在的都不会添加成功 -
get 获取
mget
获取一个或多个key-value对 -
del 删除
-
incr decr
key对应的value数组-1 +1 -
getset
设置当前的key的value,同时返回原来的value
-
Hash哈希表
-
Redis hash是一个键值对集合。
var user1 map[string]string
-
Redis hash是一个string类型的field和value的映射表,hash适用于存储对象
User1 name smith age 30
-
CRUD
-
hset key1 field1 value1
修改或添加hmset key1 field1 value1 field2 value2 ...
设置多个keyhsetnx
为哈希表中不存在的字段赋值。如果字段已经存在于哈希表中,操作无效。如果 key 不存在,一个新哈希表被创建 -
hget key1 field1
获取hgetall key
获取所有hmget key1 field1 field2...
获取多个key -
hdel key
删除 -
hlen key
获取key对应的字段个数 -
hexists key field
判断是否存在字段 -
hkeys key
返回此key的所有字段名 -
hvals key
返回此key的所有values
-
List列表
- 该类型是一个插入顺序排序的字符串元素集合, 基于双链表实现。可以在头部插入也可在尾部插入
- List本质是一个链表,List的元素是有序的,元素的值可以重复
- CRUD
LPUSH key element [element ...]
redis LPUSH用于将一个或多个值插入到列表key
的头部。返回执行push操作后列表的长度。RPUSH key element [element ...]
向存存储在 key 中的列表的尾部插入所有指定的值。返回执行 push 操作后的列表长度LPOP key
用于删除并返回存储在 key中的列表的第一个元素。key不存在的时候返回 nil。RPOP key
用于移除并返回列表key
的最后一个元素。LSET key index element
用于设置列表 key 中 index 位置的元素值element。LLEN key
用于返回存储在key
中的列表长度。LINDEX key index
返回列表 key 里索引 index 位置存储的元素LRANGE KEY_NAME START END
用于返回列表中指定区间内的元素,区间以偏移量 START 和 END 指定。
Set集合
- Set类型是一种无顺序集合, 它和List类型最大的区别是:集合中的元素没有顺序, 且元素是唯一的。
- Set类型主要应用于:在某些场景,如社交场景中,通过交集、并集和差集运算,通过Set类型可以非常方便地查找共同好友、共同关注和共同偏好等社交关系。
- CRUD
SADD key member [member ...]
将一个或多个成员元素加入到集合中,已经存在于集合的成员元素将被忽略。返回新成功添加到集合里元素的数量,不包括已经存在于集合中的元素。SPOP key [count]
用于从集合key
中删除并返回一个或多个随机元素。SMEMBERS key
返回存储在key
中的集合的所有的成员。 不存在的集合被视为空集合。SCARD key
返回集合中元素的数量。SREM key member [member ...]
用于在集合中删除指定的元素。如果指定的元素不是集合成员则被忽略。SINTER key [key ...]
返回所有给定集合的成员交集。SDIFF key [key ...]
返回第一个集合与其他集合之间的差异,也可以认为说第一个集合中独有的元素。SDIFFSTORE destination key [key ...]``SDIFFSTORE
命令的作用和SDIFF
类似,不同的是它将结果保存到destination
集合,而把结果集返回给客户端。SUNION key [key ...]
用于返回所有给定集合的并集。
ZSet顺序集合
- ZSet是一种有序集合类型,每个元素都会关联一个double类型的分数权值,通过这个权值来为集合中的成员进行从小到大的排序。与Set类型一样,其底层也是通过哈希表实现的。
- CRUD:
ZADD key [NX|XX] [GT|LT] [CH] [INCR] score member [score member ...]
用于将一个或多个member
元素及其score
值加入到有序集key
当中。ZPOPMAX key [count]
删除并返回最多count
个有序集合key
中的最高得分的成员。如未指定,count
的默认值为1。ZPOPMIN key [count]
删除并返回最多count
个有序集合key
中最低得分的成员。如未指定,count
的默认值为1。ZREM key member [member ...]
用于从有序集合key
中删除指定的成员member
。ZCARD key
用于返回有序集的成员个数。ZCOUNT key min max
返回有序集key
中,score
值在min
和max
之间(默认包括score
值等于min
或max
)的成员的数量。ZSCORE key member
用于返回有序集key
.中成员member
的分数。ZREVRANGE key start stop [WITHSCORES]
返回有序集key
中,指定区间内的成员。其中成员的位置按score值递减(从高到低)来排列。
Golang操作Redis
- 下载使用第三方开源的redis库
string
import (
"fmt"
"github.com/garyburd/redigo/redis"
)
func main() {
conn, err := redis.Dial("tcp", "localhost:6379")
if err != nil {
fmt.Printf("dial err: %v\n", err)
return
}
defer conn.Close()
reply, err2 := conn.Do("set", "name", "tom")
if err2 != nil {
fmt.Printf("set cmd err2: %v\n", err2)
}
fmt.Printf("reply: %v\n", reply) // reply: OK
fmt.Printf("reply: %T\n", reply) // reply: string
replyGet, err3 := conn.Do("get", "name")
if err3 != nil {
fmt.Printf("get cmd err: %v\n", err3)
}
fmt.Printf("replyGet: %T\n", replyGet) // replyGet: []uint8
fmt.Printf("replyGet: %v\n", string(replyGet.([]uint8))) // replyGet: tom
conn.Do("mset", "name1", "jack", "name2", "smith")
reply2, _ := redis.Strings(conn.Do("mget", "name", "name1", "name2"))
fmt.Printf("reply2: %v\n", reply2) // reply2: [tom jack smith]
fmt.Printf("reply2: %T\n", reply2) // reply2: []string
}
Hash
import (
"fmt"
"strconv"
"github.com/garyburd/redigo/redis"
)
type User struct {
Name string
Age int
Address string
}
func main() {
conn, err := redis.Dial("tcp", "localhost:6379")
if err != nil {
fmt.Printf("Dial err: %v\n", err)
}
defer conn.Close()
conn.Do("hset", "user4", "name", "marry", "age", 40, "address", "ustl")
reply, _ := redis.StringMap(conn.Do("hgetall", "user4"))
fmt.Printf("reply: %v\n", reply) // reply: map[address:ustl age:40 name:marry]
var user User = User{}
for key, val := range reply {
switch key {
case "name":
user.Name = val
case "age":
user.Age, _ = strconv.Atoi(val)
case "address":
user.Address = val
}
}
fmt.Printf("user: %v\n", user) // user: {marry 40 ustl}
}
其他操作都类似
链接池
- 事先初始化一定数量的链接,放入到链接池
- 当go需要操作redis时,直接从redis链接池取出链接即可
- 这样可以节省临时获取redis链接的时间,从而提高效率
import (
"fmt"
"github.com/garyburd/redigo/redis"
)
var pool *redis.Pool
func init() {
pool = &redis.Pool{
MaxIdle: 8,
MaxActive: 0,
IdleTimeout: 100,
Dial: func() (redis.Conn, error) {
return redis.Dial("tcp", "localhost:6379")
},
}
}
func main() {
// 1. 从链接池中取出链接
conn := pool.Get()
// 2. 关闭资源
defer conn.Close()
// 3. 操作redis
reply, err := redis.StringMap(conn.Do("hgetall", "user1"))
if err != nil {
fmt.Printf("err: %v\n", err)
}
fmt.Printf("reply: %s\n", reply) // reply: map[address:dlmu age:30 name:tom]
}