go语言系列-redis
redis的使用
redis 基本介绍
-
redis是nosql数据库,不是传统的关系型数据库 官网: https://redis.io/ 和
-
redis:remote dictionary server(远程字典服务器),redis性能非常高,单机能够达到15w qps,通常适合做缓存,也可以持久化。
-
是完全开源免费的,高性能的(key/value)分布式内存数据库,基于内存运行并支持持久化的nosql数据库,是最热门的nosq|数据库之一也称为数据结构服务器
redis的安装
链接:https://pan.baidu.com/s/1qtytkepsgza93kca76eatq
提取码:au10
下载后直接解压就有redis的服务器端程序(redis- server.exe)和客户端程序(redis-cli.exe),直接双击即可运行,并不需要安装。
redis 操作的基本原理图
redis的安装和基本使用
redis的启动
启动redis的服务器端程序(redis-server.exe),直接双击即可运行
redis的操作指令一览
redis的基本使用
说明:redis安装好后,默认有16个数据库,初始默认使用0号库,编号..15
-
添加key-val [set]
-
查看当前redis的所有key [keys *]
-
获取key对应的值. [get key]
-
切换redis数据库[select index]
-
如何查看当前数据库的key-val数量[dbsize]
-
清空当前数据库的key-val和清空所有数据库的key-val [fiushdb flushall]
redis的crud操作
redis的五大数据类型
redis的五大数据类型是: string(字符串)、hash (哈希)、list(列表)、set(集 合)和zset(sorted set:有序集合)
string(字符串) -介绍
string是redis最基本的类型,一个key对应一个value.
string类型是二进制安全的。除普通的字符串外,也可以存放图片等数据。
redis中字符串value最大是512m
举例,存放一个地址信息:
address 北京*
说明:
key : address
value:北京*
127.0.0.1:6379> set address beijing ok 127.0.0.1:6379> get address "beijing"
string(字符串)-crud
举例说明redis的string 字符串的crud操作.
set[如果存在就相当于修改,不存在就是添加]/get/del
127.0.0.1:6379> del address (integer) 1 127.0.0.1:6379> get address (nil)
string(字符串)-使用细节和注意事项
setex(set with expire)键秒值
127.0.0.1:6379> setex mess01 10 hello,you ok 127.0.0.1:6379> get mess01 "hello,you" 127.0.0.1:6379> get mess01 "hello,you" 127.0.0.1:6379> get mess01 (nil)
mset[同时设置一个或多个key-value 对]
mget[同时获取多个key-val]
127.0.0.1:6379> mset worker01 tom worker02 scott ok 127.0.0.1:6379> get worker02 "scott" 127.0.0.1:6379> mget worker01 worker02 1) "tom" 2) "scott"
hash (哈希,类似golang里的map)-介绍
基本的介绍
redis hash是一个键值对集合。var user1 map[string]string
redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象。
举例,存放一个user信息:(user1)
userl name "smith" age 30 job "golang coder"
说明:
key : userl
name张三 和age 30 就是两对field-value
hash (哈希,类似golang里的map) -crud
举例说明redis的hash 的crud的基本操作.
hset/hget/hgetall/hdel
演示添加user信息的案例(name,age )
127.0.0.1:6379> hgetall user1 1) "name" 2) "smith" 3) "age" 4) "30" 5) "job" 6) "golang coder"
hash-使用细节和注意事项
在给user设置name和age时,前面我们是一一步-一步设置,使用hmset和hmget 可以一次性来设置多个filed 的值和返回多个field 的值。
hlen 统计一个hash有几个元素
hexists key field 查看哈希表key中,给定域field是否存在
127.0.0.1:6379> hmset user2 name jerry age 110 job "java coder" ok 127.0.0.1:6379> hmget user2 name age job 1) "jerry" 2) "110" 3) "java coder" 127.0.0.1:6379> hlen user2 (integer) 3 127.0.0.1:6379> hexists user2 name (integer) 1 127.0.0.1:6379> hexists user2 name2 (integer) 0
hash练习
举例,存放一个student信息:
stu1 name张三age 30 score 80 address北京
说明:
通过相关指令,完成对student的crud操作
list(列表) - 介绍
列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。
list本质是个链表,list的元素是有序的,元素的值可以重复.
举例 存放多个地址信息:
city 北京 天津 上海
说明:
key:city
北京 天津 上海 就是三个元素
入门案例
127.0.0.1:6379> lpush city berjing shanghai tianjing (integer) 3 127.0.0.1:6379> lrange city 0 -1 1) "tianjing" 2) "shanghai" 3) "berjing"
list (列表) -crud
举例说明redis的list的crud操作。
lpush/rpush/lrange/lpop/rpop/del/
说明
list画图帮助理解(可以把list想象成一根管道)
herolist的演示
127.0.0.1:6379> lpush herolist aaa bbb ccc (integer) 3 127.0.0.1:6379> lrange herolist 0 -1 1) "ccc" 2) "bbb" 3) "aaa" 127.0.0.1:6379> rpush herolist ddd eee (integer) 5 127.0.0.1:6379> lrange herolist 0 -1 1) "ccc" 2) "bbb" 3) "aaa" 4) "ddd" 5) "eee" 127.0.0.1:6379> rpop herolist "eee" 127.0.0.1:6379> lrange herolist 0 -1 1) "ccc" 2) "bbb" 3) "aaa" 4) "ddd" 127.0.0.1:6379> del herolist (integer) 1 127.0.0.1:6379> lrange herolist 0 -1 (empty list or set)
list-使用细节和注意事项
(1) lindex,按照索引下标获得元素(从左到右,编号从0开始.)
(2) llen key
返回列表key的长度,如果key不存在,则key被解释为一个空列表,返回0
(3) list的其它说明
list数据,可以从左或者右插入添加;
如果值全移除,对应的键也就消失了。
set(集合) - 介绍
redis 的set是string类型的无序集合。
底层是 hashtable数据结构,set也是存放很多字符串元素,字符串元素是无序的,而且元素的值不能重复
举例,存放多个邮件列表信息:
email sgg@sohu.com tom@sohu.com
说明:
key : email
tn@sohu.com tom@sohu.com就是二个元素
127.0.0.1:6379> sadd emails tom@sohu.com jack@qq.com (integer) 2 127.0.0.1:6379> smembers emails 1) "jack@qq.com" 2) "tom@sohu.com" 127.0.0.1:6379> sadd emails kk@yy.com yy@sohu.com (integer) 2 127.0.0.1:6379> smembers emails 1) "kk@yy.com" 2) "jack@qq.com" 3) "tom@sohu.com" 4) "yy@sohu.com" 127.0.0.1:6379> sadd emails tom@sohu.com (integer) 0 127.0.0.1:6379> smembers emails 1) "kk@yy.com" 2) "jack@qq.com" 3) "tom@sohu.com" 4) "yy@sohu.com"
set(集合) - crud
举例说明redis的set 的crud操作.
sadd
smembers[取出所有值]
sismember[判断值是否是成员]
srem [删除指定值]
演示添加多个电子邮件信息的案例
127.0.0.1:6379> sismember emails tom@sohu.com (integer) 1 127.0.0.1:6379> sismember emails tom~@sohu.com (integer) 0 127.0.0.1:6379> srem emails tom@sohu.com (integer) 1 127.0.0.1:6379> smembers emails 1) "jack@qq.com" 2) "yy@sohu.com" 3) "kk@yy.com"
set练习
举例,存放一个商品信息:
包括商品名、价格、生产日期。
完成对应的crud操作
golang操作redis
安装第三方开源redis库
1)使用第三方开源的redis库: github.com/garyburd/redigo/redis
2)在使用redis前,先安装第三方redis库,在gopath路径下执行安装指令:
e:\gostudent>go get github.com/garyburd/redigo/redis
3)安装成功后,可以看到如下包
特别说明:在安装redis库前,确保已经安装并配置了git, 因为是从github下载安装redis库的,需要使用到git。
e:\gostudent>go get github.com/garyburd/redigo/redis \# cd .; git clone -- https://github.com/garyburd/redigo e:\gostudent\src\github.com\garyburd\redigo cloning into 'e:\gostudent\src\github.com\garyburd\redigo'... fatal: unable to access 'https://github.com/garyburd/redigo/': failed to connect to github.com port 443: timed out package github.com/garyburd/redigo/redis: exit status 128
多执行几次就好了 原因大家都懂
set/get接口
说明:通过golang添加和获取key-value 【比如name-tom~】
package main import ( "fmt" "github.com/garyburd/redigo/redis" //引入redis包 ) func main() { //通过go向redis写入数据和读取数据 //1. 链接到redis conn, err := redis.dial("tcp", "127.0.0.1:6379") if err != nil { fmt.println("redis.dial err =", err) return } defer conn.close() //关闭... //2. 通过go向redis写入数据strinf [key-val] _, err = conn.do("set", "name","tomjerry 猫猫") if err != nil { fmt.println("set err = ", err) return } //3. 通过go 向redis读取数据string [key-val] r, err := redis.string(conn.do("get","name")) if err != nil { fmt.println("set err = ", err) return } //因为返回r是interface{} //因为name对应的值是string ,因此我们需要转换 //namestring := r.(string) fmt.println("操作ok", r) } //操作ok tomjerry 猫猫
操作hash
说明: 通过golang对redis操作hash数据类型
对hash数据结构,field-val 是一个一个放入和读取
代码:
import ( "fmt" "github.com/garyburd/redigo/redis" //引入redis包 ) func main() { //通过go向redis写入数据和读取数据 //1. 链接到redis conn, err := redis.dial("tcp", "127.0.0.1:6379") if err != nil { fmt.println("redis.dial err =", err) return } defer conn.close() //关闭... //2. 通过go向redis写入数据string [key - val] _,err = conn.do("hset","user01","name","john") if err != nil { fmt.println("hset err = ", err) return } _, err = conn.do("hset","user01","age",18) if err != nil { fmt.println("hset err =", err) return } //3. 通过go向redis读取数据 r, err := redis.string(conn.do("hget","user01","name")) if err != nil { fmt.println("hget err = ", err) return } r2, err := redis.int(conn.do("hget","user01","age")) if err != nil{ fmt.println("hget err =", err) return } //因为返回r是interface{} //因为name对应的值是string,因此需要转换 //namestring := r.(string) fmt.printf("操作ok r1 = %v r2 = %v\n", r, r2) } //操作ok r1 = john r2 = 18 对hash数据结构,field-val是批量放入和读取 import ( "fmt" "github.com/garyburd/redigo/redis" //引入redis包 ) func main() { //通过go向redis写入数据和读取数据 //1. 链接到redis conn, err := redis.dial("tcp", "127.0.0.1:6379") if err != nil { fmt.println("redis.dial err =", err) return } defer conn.close() //关闭... //2. 通过go向redis写入数据string [key - val] _,err = conn.do("hmset","user02","name","john","age",19) if err != nil { fmt.println("hmset err = ", err) return } //3. 通过go向redis读取数据 r, err := redis.strings(conn.do("hmget","user02","name","age")) if err != nil { fmt.println("hmget err = ", err) return } for i, v := range r { fmt.printf("r[%d] = %s\n", i, v) } } //r[0] = john //r[1] = 19
批量set/get数据
说明:通过golang对redis操作,一次操作可以set/get多个key-val数据
核心代码:
_, err = c.do("mset", "name",”zisefeizhu","address", "中国") r, err := redis.strings(c.do("mget", 'name", " address")) for. ,v := range r { fmt.println(v) }
给数据设置有效时间
说明: 通过golang对redis操作,给key-value设置有效时间
核心代码:
//给name数据设置有效时间为10s
_,err = c.do("expire", "name", 10)
操作list
说明: 通过golang对redis操作list 数据类型
核心代码:
_, err = c.do("lpush", "herolist", "no1:宋江",30, "no2:卢俊义", 28) r, err := redis.string(c.do("rpop", "herolist"))
redis链接池
说明:通过golang对redis操作,还可 以通过redis链接池,流程如下:
1) 事先初始化一定数量的链接,放入到链接池
2) 当go需要操作redis时,*直接从redis链接池取出链接*即可。
3) 这样可以节省临时*获取redis链接*的时间,从而提高效率.
4) 示意图
*链接池使用案例*
import ( "fmt" "github.com/garyburd/redigo/redis" ) //定义一个全局的pool var pool *redis.pool //当启动程序时,就初始化链接池 func init() { pool = &redis.pool{ dial: func() (redis.conn, error) { //初始化链接的代码,链接哪个ip的redis return redis.dial("tcp","localhost:6379") }, maxidle: 8, //最大空闲链接数 maxactive: 0, //表示和数据库的最大链接数,0 表示没有限制 idletimeout: 100, //最大空闲时间 } } func main() { //先从pool取出一个链接 conn := pool.get() defer conn.close() _, err := conn.do("set","name","汤姆猫~") if err != nil { fmt.println("conn.do err=", err) return } //取出 r, err := redis.string(conn.do("get","name")) if err != nil { fmt.println("conn.do err =", err) return } fmt.println("r =", r) //如果要从pool 取出链接,一定要保证链接池是没有关闭 // pool.close() conn2 := pool.get() _, err = conn2.do("set", "name2", "汤姆猫~2") if err != nil { fmt.println("conn.do err ~~=", err) return } //取出 r2, err := redis.string(conn2.do("get","name2")) if err != nil { fmt.println("conn.do err =", err) return } fmt.println("r =", r2) //fmt.println("conn2 =", conn2) } //r = 汤姆猫~ //r = 汤姆猫~2 再来一例 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() { conn := pool.get() defer conn.close() _, err1 := conn.do("hmset", "user1", "name", "beijing", "address", "beijing") if err1 != nil { fmt.println("hmset err=", err1) return } _, err3 := conn.do("hmset", "user2", "name", "wuhan", "address", "wuhan") if err3 != nil { fmt.println("hmset err=", err3) return } //向redis读取数据,返回的r是个空接口 r, err2 := redis.strings(conn.do("hmget", "user1", "name", "address")) if err2 != nil { fmt.println("hmget err=", err2) return } for i, v := range r { fmt.printf("r[%d]=%v\n", i, v) } } //r[0]=beijing //r[1]=beijing
上一篇: 纯虚函数与基类指针数组的运用 代码参考
下一篇: Linux CentOS7 的安装