Redis安装和基本原理请查阅相关资料学习。
Redis基础知识和开发使用:
1. 0 - 15 共计16个库。
2. 典型的KV存储方式。
3. 常用操作命令:
(1) 添加kv: set
(2) 查找所有key: keys <pattern正则>
(3) 查找key对应的value: get
(4) 切换数据库: select <num 0-15>
(5) 查看key-value数量: dbsize (无参数为当前库)
(6) 清空数据库: flushdb(当前库) ; flushall(所有库)
4. 五种数据类型: String,hash(类字典,多对kv),list,set,zset(有序集合):
-
(1) String:
redis最基本类型,kv对;
二进制存放,除了字符串还能放图片等数据,程序读出来没有问题,二进制保存中文。
字符串value最大值512MB;
setex(set with expire): setex <keyname> <n seconds> <value> //多少秒过后,这个value就被销毁了; mset(多个kv对设置): mset <k1> <v1> <k2> <k2> //如何获得: mget <k1> <k2>。
-
(2) Hash:
键值对集合,类似字典,var golang map[string]string;
特别适合用于存储对象,也就是golang中的结构体;
hset cxk hobby sing ; hset cxk name caixukun // hget cxk name 就能取到name对应的value。 hmset cxk name caixk age 20 song "鸡你太美" // hmget cxk name age song 一次取到设置并取多个字段的values。 hlen cxk //查看Hash元素有多少个。 hexists cxk song //查看cxk这个hash中是否有song这个字段。
-
(3) List:
简单的字符串列表,按照插入顺序进行排序,可以添加一个元素到列表头部或者尾部;
List本质是一个链表,List的元素是有序的(List[n]),元素值可以重复;
注意lpop/rpop用法很常见;lpush类似压栈,rpush类似队列。 -
(4) Set (Zset同理):
Set是string类型的无序集合;
底层是Hashtable数据结构,存放很多字符串元素,字符串元素是无序的,而且元素值不能重复,适合存放例如员工ID号,电子邮件,电话号码,QQ号等唯一不重复的内容;
sadd emails [email protected] [email protected] //创建并添加集合的k名和v的内容; smembers emails //遍历所有集合中的内容; sismenber emails damn //检查集合中是否存在damn,有返回1,没有就返回0; srem emails [email protected] //删除集合中指定值;
5. 数据类型与CRUD:
(1) String:
CU: set <keyname> <valuename> //set的key没有就创建,有就修改
D:del <keyname>
R:get <keyname>
(2) Hash:
CU: hset <hashname> <keyname> <valuename>
R: hget <hashname> <keyname> ; hgetall
D: hdel <hashname>
(3) List:
CU: lpush/rpush <listname> value1 value2 value3 … // left right 分别插入数据
lpop/rpop <listname> // 左取/右取 各一个元素
R: lrange <listname> [起始数字] [结束数字] // 只有左边开始显示从起始0到末尾-1中的一段数据
lindex <listname> <index> // 通过下标拿到list中对应的元素值
llen <listname> // 查看元素个数
D: del <listname>
(4) Set:
CU: sadd <keyname> <value1> <value2>
R: smembers <keyname> //遍历所有值;
sismember <keyname> <dest-value> //是否存在x,存在1,不存在0;
D: srem <keyname> <dest-value> //删除成功返回1,不成功返回0;
通过Golang如何操作redis
- 保证系统中安装了git。
- 切换至GOPATH目录下: “go get github.com\garyburd\redigo\redis” 中可以下载相关的redis包到src下,从而import redis包,使用相关的属性和方法。
案例1:Golang操作redis,以string字符串说明,其余数据类型传递参数与redis命令行一模一样:
package main
import (
"fmt"
"github.com/garyburd/redigo/redis"
)
func main() {
//连接数据库
conn, err := redis.Dial("tcp","127.0.0.1:6379")
if err != nil {
fmt.Println("连接失败,错误为:",err)
return
}
defer conn.Close()
//添加一对键值对,我们所需要的仅仅是添加结果成功就可以,无需返回值
_, err = conn.Do("set", "email", "damn") //conn.Do()用的是最多的,把命令行中的args一个个写进去
if err != nil {
fmt.Println("设置kv失败,错误原因为:",err)
return
}
_, err = conn.Do("setex", "email1", 10,"shit") //conn.Do()用的是最多的,把命令行中的args一个个写进去
if err != nil {
fmt.Println("设置kv失败,错误原因为:",err)
return
}
//取得一个键对应的一个值,判断获取的值得类型为xx
//get返回时空接口类型,使用断言报错,直接使用redis提供的转换方法即可
res, err := redis.String(conn.Do("get","email"))
if err != nil {
fmt.Println("获取key失败,错误原因为:",err)
return
}
fmt.Println(res)
}
案例2:Golang操作redis,hash字符串的使用
package main
import (
"fmt"
"github.com/garyburd/redigo/redis"
)
func main() {
//连接数据库
conn, err := redis.Dial("tcp","127.0.0.1:6379")
if err != nil {
fmt.Println("连接失败,错误为:",err)
return
}
defer conn.Close()
//添加一个hash
_, err = conn.Do("hmset", "hhash", "name","damn","age",27)
if err != nil {
fmt.Println("设置kv失败,错误原因为:",err)
return
}
//取得一个键对应的一个值,判断获取的值得类型为xx
//get返回时空接口类型,使用断言报错,直接使用redis提供的转换方法即可
res, err := redis.Strings(conn.Do("hmget","hhash","name","age")) //注意这里变为Strings
if err != nil {
fmt.Println("获取key失败,错误原因为:",err)
return
}
for i, v := range res { //res应该是集合类数据,在golang中也应该是数组切片之类的。
fmt.Println(v) //遍历的方式,也可以带上索引或者不带
}
}
Redis连接池
- 实现初始化一定数量的链接,放入链接池;
- Go需要操作redis时,直接从链接池取出链接即可;
- 这样可以节省临时获取redis链接的时间,从而提高效率。
案例:init()创立redis链接池,后面代码直接从链接池中取得链接资源并进行读写
package main
import (
"fmt"
"github.com/garyburd/redigo/redis"
)
var pool *redis.Pool
/*
type Pool struct {
Dial func() (Conn, error)
// Maximum number of idle connections in the pool.
MaxIdle 8 //最大空闲数为8
MaxActive 0 //0表示无限制链接,支持最高并发数
IdleTimeout 100 //time.Duration
}
*/
func init() { //初始化函数,执行main之前优先创建链接池,链接池的意义在于迅速响应go链接,不用从头开始建立tcp链接
pool = &redis.Pool{
Dial: func() (redis.Conn, error){
return redis.Dial("tcp","127.0.0.1:6379")
},
MaxIdle: 8, //最大空闲数为8
MaxActive: 0, //0表示无限制链接,支持最高并发数
IdleTimeout: 100, //time.Duration
}
}
func main() {
//从创建好的链接池中取出一个链接
/*
func (p *Pool) Get() Conn {
pc, err := p.get(nil)
if err != nil {
return errorConn{err}
}
return &activeConn{p: p, pc: pc}
}
*/
conn := pool.Get() //从redis链接池中取出一个链接,和之前redis.Dial是一个意思
defer conn.Close() //开销类资源一定要使用defer关闭,如果要取值一定要保证链接池开启,关闭后 get on closed pool报错
//链接redis,创建添加一个kv,并查询kv
_, err := conn.Do("Set","cxk","鸡你太美")
if err != nil {
fmt.Println("SET 添加字段有误,错误为:",err)
return
}
ret, err1 := redis.String(conn.Do("Get","cxk"))
if err1 != nil {
fmt.Println("GET 读取字段有误,错误为:",err1)
return
}
fmt.Println("Get 取值为:",ret) //Get 取值为: 鸡你太美
}