redis 是一个开源的、使用c编写的支持网络交互的、科技与内存也可持久化的key-value数据库
go getgithub.com/garyburd/redigo
利用redis.Dail进行监听、返回一个连接器、可以使用go的类型断言将返回的interface转为对应的类型
可以利用pipe操作并发操作
可以进行发布订阅
事物操作
mysql和redis的区别:
MySQL的数据存储在data目录下frm ibd后缀的文件中、存储在机器/服务器的硬盘中、所以MySQL读写数据都需要从硬盘读取、磁盘的容量、带宽的大小就影响了网站的访问速度、读取的方式、也就是sql语句、次数和效率也会影响读取效率
当访问量和并发都很大的时候、MySQL就撑不住了、MySQL的连接池并发数max为500-1000
可以选择慢查询优化、cdn、页面静态化、ngix负载均衡策略、分布式数据库来进行sql优化、也可以使用高速缓存、例如redis。
redis :高并发、内存高速cache、处理读写io的高并发容忍、将通常被使用来将那些经常被访问的内容缓存到内存中、主从同步(将数据同步到多台从数据库上、提高读取性能)
redis不仅仅支持简单的k-v类型的数据、还支持list、set、zset、hash等数据结构的存储
redis单个value的最大限制是1GB
redis在3.0版本后支持在服务器端构建分布式存储、redis Cluster是一个实现了分布式且允许单点故障的高级版本
链接数据库:redis.Dail("tcp","127.0.0.1:6379")
1、以redigo为例、当然还有redix、redix在操作查询删除添加时、用的是conn.Cmd
import (
"github.com/garyburd/redigo/redis"
"fmt"
)
func connDb() {
//redis作为中间件的数据库、需要和服务器相连
//创建监听器、创建连接请求
conn, err := redis.Dial("tcp", "127.0.0.1:6379")
if err != nil {
fmt.Println("redis.Dial error", err)
return
}
defer conn.Close()
saveDb( conn )
readFromDB( conn )
deleFromDB( conn )
}
//写入
func saveDb( conn redis.Conn ){
//EX 为这个值得过期时间
//批量写入、单个写入的话、MSET改为SET
_,err := conn.Do("MSET","name","superWang","SEX","F","EX","50")
if err != nil{
fmt.Println("conn.Do error",err)
}
fmt.Println("save success")
}
func readFromDB( conn redis.Conn){
//单个读取数据,conn.Do的第一个参数为命令类型、因为我们是读取、所以是GET、其余参数为想要查找的值
username,err := redis.String(conn.Do("GET","name"))
userSex,_ := redis.String(conn.Do("GET","SEX"))
if err != nil{
fmt.Println("redis.String error",err)
}else {
fmt.Printf("Get mykey: %v \n",username)
}
fmt.Printf("Get mykey: %v \n",userSex)
//批量读取
usernameall,_ := redis.Strings(conn.Do("MGET","SEX","name"))
fmt.Printf("Get mykey: %v \n",usernameall)
}
func deleFromDB( conn redis.Conn){
_,err := conn.Do("DEL","name","SEX")
if err != nil{
fmt.Println("deleFromDB error",err)
}
fmt.Println("delete success")
}
func main(){
connDb()
}
运行结果为
解释一下EX过期时间:如果设置了这个时间、则在当前的key过期时间为设置时间、不设置则当前的key永远有效
看了很多文章、找了很多解释、想弄明白为什么要选择json作为读写到redis的通用配置格式
go的配置格式右ini,json,yaml,xml等等、xml比较繁琐、ini不适用于太多层次结构的
json中的RawMassage、它主要用来告诉go延迟解析
2、利用json类型转换的写入读取:
package main
import (
"github.com/garyburd/redigo/redis"
"fmt"
"encoding/json"
)
func connDb() {
//redis作为中间件的数据库、需要和服务器相连
//创建监听器、创建连接请求
conn, err := redis.Dial("tcp", "127.0.0.1:6379")
if err != nil {
fmt.Println("redis.Dial error", err)
return
}
defer conn.Close()
saveJsonDataToDB( conn )
readJsonDataFromDB( conn )
}
//写json
func saveJsonDataToDB( conn redis.Conn ){
imap := map[string]string{ "name" : "waiwaigo","phone":"1342132132" }
//将map进行类型转换、转换成字符切片
value,_ := json.Marshal(imap)
n,err := conn.Do("SETNX","jsonkey",value)
if err != nil {
fmt.Println("conn.Do SETNX error ", err)
return
}
if n == int64(1){
fmt.Println("success")
}
}
//读json
func readJsonDataFromDB( conn redis.Conn){
var imspGet map[string]string
valueGet ,err := redis.Bytes(conn.Do("GET","jsonkey"))
if err != nil {
fmt.Println("redis.Bytes error ", err)
return
}
//将读取的数据转换为map类型
errshal := json.Unmarshal(valueGet,&imspGet)
if errshal != nil {
fmt.Println("son.Unmarshal error ", err)
return
}
for i,v :=range imspGet{
fmt.Println(i,v)
}
}
func main(){
connDb()
}
3、列表操作
package main
import (
"github.com/garyburd/redigo/redis"
"fmt"
)
func connDb() {
//redis作为中间件的数据库、需要和服务器相连
//创建监听器、创建连接请求
conn, err := redis.Dial("tcp", "127.0.0.1:6379")
if err != nil {
fmt.Println("redis.Dial error", err)
return
}
defer conn.Close()
saveListToDB( conn )
readListFromDB( conn )
}
//写json
func saveListToDB( conn redis.Conn ) {
//写入列表、命令为lpush
_, err := conn.Do("lpush", "username", "zhangsan")
if err != nil {
fmt.Println("conn.Do lpush error ", err)
return
}
_, err = conn.Do("lpush", "username", "lisi")
if err != nil {
fmt.Println("conn.Do lpush error ", err)
return
}
_, err = conn.Do("lpush", "username", "wangwu")
if err != nil {
fmt.Println("conn.Do lpush error ", err)
return
}
}
//读列表
func readListFromDB( conn redis.Conn ){
//想要读取的下标值、这块我也不是太清楚、因为如果把1去掉就显示两个值,如果是0和2、就显示三个值
values,_ := redis.Values(conn.Do("lrange","username","1","2"))
//计算列表中一共有几条数据
fmt.Printf("count : %d \n",len(values))
for _,v :=range values{
fmt.Println( string(v.([]byte)))
}
}
func main(){
connDb()
}
对于redis一般操作时,首先会创建一个连接规则(spec:= redis.Default().DB(0).Password(""),返回一个规则)自己创建 、然后创建一个新的syncClient、并连接到redis的服务器上使用,并指定ConnecttionSpec接口( client:=redis.NewSynchClientWithSpec(spec)、此时会返回一个错误信息、如果有错误则代表服务器连接失败)、接下来制定一个得到数据的规则( dbkey := "GAME:TEST:info")从client获取信息(value,err := client.Get(dbkey)此时返回一个值和错误信息、如果值为空则可以向客户端写入数据、client.Set,如果不为空则代表接收到数据)