[go学习笔记.第十七章.redis的使用] 1.redis的使用

news2025/1/27 13:04:02

1.redis基本介绍

        (1).Redis NoSQL 数据库,不是传统的关系型数据库,官网: https://redis.io/ 和http://redis.cn/

        (2).Redis: REmote Dlctionary Sever(远程字典服务器), Redis 性能非常高,单机能够达到 15w qps,通常适合做缓存,也可以持久化

        (3).完全开源免费的,高性能的(key-value)分布式内存数据库,基于内存运行并支持持久化的 NoSOL 数据库,是最热门的Nosql数据库之一,也称为数据结构服务器 

总结:  redis ( REmote Dlctionary Sever)是一个由 Salvatore Sanfilippo 编写的key-value 存储系统,它由 C 语言编写、遵守 BSO 协议、支持网络、可基于内存亦可持久化的日志型、 key-value 类型的数据库,并提供多种语言的 API.和 Memcached 类似,它支持存储的 value 类型相对更多,包括 string(字符串)、 Iist (链表)、 set (集合)、 zset ( sorted set 一有序集合)和 hash (哈希类型).这些数据类型都支持 push / pop 、 add / remove 及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上, redis 支持各种不同的方式排序.与 memcached 一样,为了保证效率,数据都是缓存在内存中。区别的是 redis 会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步, redis 在3.0版本推出集群模式

源码部署

yum install gcc -y #安装c依赖

wget http://download.redis.io/redis-stable.tar.gz #下载稳定版本

tar zxvf redis-stable.tar.gz #解压

cd redis-stable

make PREFIX=/opt/app/redis install #指定目录编译

make install

2.redis的安装和和基本使用

        下载后直接解压就有 Redis 的服务端程序( redis - server.exe )和客户端程序(redis.exe),直接双击即可运行

(1).redis的启动

 (2).redis的操作指令一览,Redis 命令参考 — Redis 命令参考

 3.redis的基本使用

        说明:  Redis 安装好后,默认有 16 个数据库,初始默认使用0号库,编号是0,1,2,....,15

        (1).添加key-val [set]

        (2).查看当前redid的所有key [keys *]

        (3).获取 key 对应的值 [get key]

        (4).切换redis数据库库 [select index]

        (5).如何查看当前数据库的key-val数量 [dbsize]

        (6).清空当前数据库的key-val和清空所有数据库的key-val [flushdb flushall]

 4.redis的crud操作

(1).redis的五大数据类型

       redis的五大数据类型是: String(字符串)、Hash(哈希)、 List(列表)、 Set 集合)和Zset (sorted set:有序集合)

(2).string(字符串)的介绍

1).基本介绍

        string是redis的最基本的类型,一个 key对应一个value

        string类型是二进制安全的,除[普]通的字符串外,也可以存放图片等数据

        redis中字符串value 最大是 512M

         举例:

                存放一个地址信息:

                address: 北京天安门

        说明:

                 key: address

                value: 北京天安门

string的crud

        set[如果存在就相当于修改,不存在就是添加]]/get/del

2).string的使用细节 

setex(set with expire)键,设置过期时间,单位:秒

(3).hash(哈希,类似go中的map)的介绍

1).基本介绍

hash是一个链值对集合,类似于go中的map:var user1 map[string]string

hash是一个string类型的 field 和 value的映射表,hash 特别适合用于存储对象

举例,存放一个User 信息:

        user1 name "tom" age 30 job "go coder"

说明:

        key: user1

        uame  "tom"和age  30 就是两对 filed-value

2).使用细节和注意事项

1).在给 user 设置name和 age 时,前面是一步一步设置,使用hmset 和 hmget 可以一次性来设置多个filed的值和返回多个filed的值

2).hlen 统计一个hash有几个元素

3).hexists key field 查看哈希表key中,给定域filed是否存在

(4).list(列表)的介绍

1).基本介绍

列表是简单的字符串列表,按照插入顺序排序,可以添加一个元素到列表的头部(左边)或者尾部(右边)

list 本质是个链表,list的元素是有序的,元素的值可以重复

举例:

        存放多个地址信息:

                city  北京 天津 上海

说明:

        key : city 北京 天津 上海 就是三个元素

2).crud

lpush/rpush/lrange/lpop/rpop/del

说明:

        可以把list想象成一根管道

 3).list的使用细节和注意事项

a.lindex,按照索引下标获得元素(从左到右,编号从0开始

b.llen key 返回列表key的长度,如果key不存在,则 key 被解释为一个空列表,返回 0

c.list的其它说明

  • list数据,可以从左或者右插入添加
  • 如果值全移除,对应的健也就消失了

(5).set(集合)的介绍

1).基本介绍

redis的set 是string类型的无序集合

底层是 HashTable数据结构,set 也是存放很多字符串元素,字符串元素是无序的,而且元素的值不能重复

举例:存放多个邮件列表信息

         email zph@qq.com zhou@qq.com

说明:

         key: email

         zph@qq.com zhou@qq.com 就是二个元素

         redis > sadd email xx xxx

 

2).crud

sadd

smembers [取出所有值]

sismember [判断值是否是成员]

srem [删除指定值]

演示添加多个电子邮件信息的案例

5.go操作redis

5.1 安装

说明:

golang 操作redis的客户端包有多个比如redigo、go-redis,github 上 Star 最多的莫属redigo

github地址:

        https//github.com/garyburd/redigo

目前已经迁移到:         

        https://github.com/gomodule/redigo

文档:

        https//godoc.org/github.com/garyburd/redigo/redis

命令:

        go get github.com/garyburd/redigo/redis

文件中引入命令:

        import "github.com/garyburd/redigo/redis"

安装

1).使用第三方开源的 redis 库: https//github.com/garyburd/redigo/redis

2).在使用redis前,先安装第三方 redis库,在 GOPATH 路径下执行安装指令:

        D:goProject>go get github.com/garyburd/redigo/redis

3).装成功后,可以看到如下包

 特别说明:在安装redis库前,确保己经安装并配置了 Git ,因为是从 github 下载安装 Redis 库的,如果没有安装配置过 Git ,请安装配置 Git

5.2 连接

Conn接口是与Redis 协作的主要接口,可以使用Dial,DialWithTimeout或者NewConn函数来创建连接,当任务完成时,应用程序必须调用Close函数来完成操作

package main
import(
"github.com/garyburd/redigo/redis"
"fmt"
)

func main(){
    //相关代码
    conn, err = redis.Dial("tcp", "127.0.0.1:6379")
    if err != nil {
        fmt.Println("connect redis error", err)
        return     
    }
    defer conn.Close()
}

连接池 

说明:

        通过 Golang 对 Redis 操作,还可以通过 Redis 链接池,流程如下:

1).事先初始化一定数量的链接,放入到链接池

2).当go需要操作redis时,直接从redis链接池取出链接即可

3).这样可以节省临时获取redis链接的时间,从而提高效率

 代码如下: 

package main

import (
	"fmt"
	"github.com/garyburd/redigo/redis" //引入redis包
)

//定义一个全局变量
var pool *redis.Pool
//当启动程序时,就初始化连接池
func init()  {
	pool = &redis.Pool{
		MaxIdle: 8, //最大空闲连接数
		MaxActive: 0, //表示和数据库的最大连接数, 0 表示没有限制
		IdleTimeout: 100, //最大空闲时间
		Dial: func () (redis.Conn, error)  { //初始化连接的代码, 连接协议,连接哪个ip
			return redis.Dial("tcp", "127.0.0.1:6379")
		},
	}
}

func main() {
	//从pool取出一个连接
	conn := pool.Get()
	defer conn.Close()
	
	_, err := conn.Do("Set", "name", "wangwu")
	if err != nil {
		fmt.Printf("conn.do set err = %v\n", err)
		return
	}
	//取出
	res, err := conn.Do("Get", "name")
	if err != nil {
		fmt.Printf("conn.do get err = %v\n", err)
		return
	}
	fmt.Printf("conn.do get result = %v\n", res)
	//要从pool取出连接,一定要保证连接池是没有关闭的
}

5.4 命令操作

通过使用Conn接口中的do方法执行redis命令,redis 命令大全参考:http://doc.redisfans.com/

go中发送与响应对应类型:

        Do函数会必要时将参数转化为二进制字符串Go Type

redis命令响应会用以下go类型表示

可以使用go的类型断言或者 reply 辅助函数将返回的 interface { }转换为对应类型

5.5 操作示例

(1).get,set

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.Printf("redis Dial err = %v\n", err)
		return
	}
	defer conn.Close() //延时conn
	//2.通过go向redis写入数据string(key-value)
	_, err = conn.Do("Set", "name", "张三")
	if err != nil {
		fmt.Printf("redis set err = %v\n", err)
		return
	}
	//3.通过go向redis读取数据string(key-value)
	res, err := redis.String(conn.Do("Get", "name"))
	if err != nil {
		fmt.Printf("redis set err = %v\n", err)
		return
	}
	fmt.Printf("success %v\n", res)
}

(2).设置key过期时间

    _, err = conn.Do("expire", "name", 10) // 10秒过期
	if err != nil {
		fmt.Println("set expire error:", err)
		return 
	}

(3).批量获取mget,批量设置mset

    //通过go向redis写入数据和读取数据
	//1.连接redis
	conn, err := redis.Dial("tcp", "127.0.0.1:6379")
	if err != nil {
		fmt.Printf("redis Dial err = %v\n", err)
		return
	}
	defer conn.Close() //延时conn

	//批量获取mget,批量设置mset
	_, err = conn.Do("MSet", "name", "张三", "age", 22)
	if err != nil {
		fmt.Printf("redis mset err = %v\n", err)
		return
	}

	res, err := redis.String(conn.Do("MGet", "name", "age"))
	if err != nil {
		fmt.Printf("redis mset err = %v\n", err)
		return
	} else {
		res_type := reflect.TypeOf(res)
		fmt.Printf("res type : %s\n", res_type) // []string
		fmt.Printf("mget name: %s\n", res) // "张三" 22
		fmt.Println(len(res)) //2
	}

(4).list(列表)

    //通过go向redis写入数据和读取数据
	//1.连接redis
	conn, err := redis.Dial("tcp", "127.0.0.1:6379")
	if err != nil {
		fmt.Printf("redis Dial err = %v\n", err)
		return
	}
	defer conn.Close() //延时conn

	//list
	_, err = conn.Do("LPush", "list1", "ele1", "ele2", "ele3")
	if err != nil {
		fmt.Printf("redis LPush err = %v\n", err)
		return
	}
	res, err := redis.String(conn.Do("LPop", "list1"))
	if err != nil {
		fmt.Printf("redis LPop err = %v\n", err)
		return
	} else {
		res_type := reflect.TypeOf(res)
		fmt.Printf("res type : %s\n", res_type) // []string
		fmt.Printf("mget name: %s\n", res) // ele3
	}

(5).hash(哈希)

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.Printf("redis Dial err = %v\n", err)
		return
	}
	defer conn.Close() //延时conn
	//hset方式单个写入
	//2.通过go向redis写入数据hash 
	_, err = conn.Do("HSet", "user1", "name", "张三")
	if err != nil {
		fmt.Printf("redis hset err = %v\n", err)
		return
	}
	_, err = conn.Do("HSet", "user1", "age", 22)
	if err != nil {
		fmt.Printf("redis hset err = %v\n", err)
		return
	}
	//hget方式单个获取
	//3.通过go向redis读取数据hash
	resName, err := redis.String(conn.Do("HGet", "user1", "name"))
	if err != nil {
		fmt.Printf("redis hset err = %v\n", err)
		return
	}
	resAge, err := redis.Int(conn.Do("HGet", "user1", "age"))
	if err != nil {
		fmt.Printf("redis hset err = %v\n", err)
		return
	}
	fmt.Printf("success user1 name=%v, age=%v\n", resName, resAge)

	//hmset批量方式多个写入
	_, err = conn.Do("HMSet", "user2", "name", "李四", "age", 99)
	if err != nil {
		fmt.Printf("redis hmset err = %v\n", err)
		return
	}
	//hmget批量方式多个获取
	res, err := redis.Strings(conn.Do("HMGet", "user2", "name", "age"))
	if err != nil {
		fmt.Printf("redis hmset err = %v\n", err)
		return
	}
	for i, v := range res {
		fmt.Printf("res[%v] = %v\n", i, v)
	}
}

(6).string

6.案例

要求:通过终端输入三个monster信息,使用go操作redis,存放到redis中[可以使用hash类型]

package main

import(
	"fmt"
	"strconv"
	"github.com/garyburd/redigo/redis" //引入redis包
)

func main()  {
	//连接redis
	conn, err := redis.Dial("tcp", "127.0.0.1:6379")
	if err != nil {
		fmt.Printf("redis Dial err = %v\n", err)
		return
	}
	defer conn.Close() //延时conn
	
	//Monster信息:name,age, skill
	//要求:通过终端输入三个monster信息,使用go操作redis,存放到redis中[可以使用hash类型]
	//遍历所有monster信息,并显示到终端
	for i := 1; i <= 3; i++ {
		fmt.Printf("第%d个monster信息:\n", i)
		var name string
		var age int
		var skill string
		fmt.Printf("请输入第%d个monster的姓名:", i)
		fmt.Scanln(&name)
		fmt.Printf("请输入第%d个monster的年龄:", i)
		fmt.Scanln(&age)
		fmt.Printf("请输入第%d个monster的技能:", i)
		fmt.Scanln(&skill)

		//hmset方式批量写入
		//通过go向redis写入数据hash 
		_, err = conn.Do("HMSet", "monster" + strconv.Itoa(i), "name", name, "age", age, "skill", skill)
		if err != nil {
			fmt.Printf("redis hmset err = %v\n", err)
			return
		}
	}

	//先获取所有keys
	keys, err := redis.Strings(conn.Do("Keys", "monster*"))
	if err != nil {
		fmt.Printf("redis keys err = %v\n", err)
		return
	}
	//遍历keys
	for index, monster := range keys {
		//hmget批量方式多个获取
		res, err := redis.Strings(conn.Do("HMGet", monster, "name", "age", "skill"))
		if err != nil {
			fmt.Printf("redis hmGet err = %v\n", err)
			return
		}
		//遍历单个monster 的hash
		for i, v := range res {
			fmt.Printf("第%d个monster结果: res[%v] = %v\n", index, i, v)
		}
	}
}

[上一节][go学习笔记.第十六章.TCP编程] 4.项目-海量用户即时通讯系统-显示在线用户列表,群聊

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/39947.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

刷爆力扣之盛最多水的容器

刷爆力扣之盛最多水的容器 HELLO&#xff0c;各位看官大大好&#xff0c;我是阿呆 &#x1f648;&#x1f648;&#x1f648; 今天阿呆继续记录下力扣刷题过程&#xff0c;收录在专栏算法中 &#x1f61c;&#x1f61c;&#x1f61c; 该专栏按照不同类别标签进行刷题&#xff…

安卓的分区一点有用知识:super、lpunpack、lpdump

我们知道这个安卓的镜像分区有很多个。 那么这个文章要介绍什么呢&#xff1f; 三个点&#xff1a; 一是现在的android支持动态分区&#xff0c;很多的东西都被放到super分区里面了&#xff0c;这个应该是可以配置的。然后super里面有比如system、vendor这种比较大的分区。那…

教务排课系统毕业设计,大学排课系统设计与实现,排课系统论文作品参考

功能清单 【后台管理员功能】 录入分院&#xff1a;录入分院名称&#xff0c;简介&#xff0c;详情 分院管理&#xff1a;管理已经录入分院&#xff0c;支持修改和删除 老师录入&#xff1a;录入老师姓名、联系方式、头像、老师简介 老师管理&#xff1a;管理所有已经录入老师…

基于Matlab模拟用于海况海洋学研究的 X 波段雷达系统(附源码)

目录 一、定义雷达系统参数 二、对海面进行建模 三、配置雷达收发器 四、生成数据多维数据集 五、处理海面回波 六、总结 七、程序 海事雷达系统在充满挑战的动态环境中运行。为了改进对感兴趣目标的检测并评估系统性能&#xff0c;必须了解海面返回的性质。 在本例中&a…

【操作系统】2.4 死锁

这一节也非常重要 2.4.1 死锁的概念 2.4.1 死锁的概念_StudyWinter的博客-CSDN博客 在并发环境下&#xff0c;各种进程因竞争资源而造成的一种互相等待对方手里的资源&#xff0c;导致各进程都阻塞&#xff0c;都无法向前推进的现象。这就是死锁&#xff0c;死锁发生后&#…

Jest API使用方法

如上面的知识图谱所示&#xff0c;一个常见的测试框架通常需要实现这些功能: ● before/after 钩子函数: 如beforeEach&#xff0c;afterEach&#xff0c; ● Mock方法&#xff1a; 函数Mock&#xff0c;时间mock等。 ● 断言: 判断一个描述是否正确&#xff0c;在Jest中常为 e…

你心心念念的RabbitMQ个人实践来了来了它来了

前言 MQ&#xff08;Message Queue&#xff09;就是消息队列&#xff0c;其有点有很多&#xff1a;解耦、异步、削峰等等&#xff0c;本文来聊一下RabbitMQ的一些概念以及使用。 RabbitMq 案例 Springboot整合RabbitMQ简单案例 基本概念 Exchange&#xff1a;消息交换机&a…

云原生系列 【基于CCE Kubernetes编排实战二】

✅作者简介&#xff1a; CSDN内容合伙人&#xff0c;全栈领域新星创作者&#xff0c;阿里云专家博主&#xff0c;阿里云问答板块版主&#xff0c;华为云享专家博主&#xff0c;掘金后端评审团成员 &#x1f495;前言&#xff1a; 最近云原生领域热火朝天&#xff0c;那么云原生…

Hystirx限流:信号量隔离和线程池隔离

背景&#xff1a; 最近工作中要处理服务高并发的问题&#xff0c;大流量场景下限流熔断降级可以说是必不可少的&#xff0c;打算对限流做一次改造&#xff0c;所以要先了解一下hytrix相关内容&#xff0c;比如了解一下线程池隔离和信号量隔离的区别。 **信号量&#xff1a;**信…

[网络工程师]-应用层协议-DHCP

BOOTP是最早的主机配置协议&#xff0c;动态主机配置协议&#xff08;Dynamic Host Configuration Protocol&#xff0c;DHCP&#xff09;则是在其基础上进行了改良的协议&#xff0c;是一种用于简化主机IP配置管理的IP管理标准。通过DHCP协议&#xff0c;DHCP服务器为DHCP客户…

集合学习笔记——Collection 全家桶

Collection是我们日常开发中使用频率非常高的集合&#xff0c;它的主要实现有List和Set,区别是List是有序的&#xff0c;元素可以重复;Set是无序的&#xff0c;元素不可以重复&#xff0c;我们简单看下继承关系&#xff1a; List的实现类主要线程不安全的ArrayList和LinkedList…

推挽输出和开漏输出-三极管-mos管

一、推挽输出 1.1推挽输出的概念 推挽&#xff08;push-pull&#xff09;输出是由两个MOS或者三极管组成&#xff0c;两个管子始终保持一个导通&#xff0c;另一个截止的状态。 图1 推挽电路示意图 当输入高电平时&#xff0c;叫做推&#xff1b; 上管Q1导通&#xff0c;下管…

【目标检测】Faster R-CNN论文的讲解

目录&#xff1a;Faster R-CNN论文的讲解一、前言二、回顾Fast R-CNN三、引入Faster R-CNN四、Faster R-CNN的介绍4.1 框架结构4.2 RPN如何产生候选区域的4.3 损失函数4.4 训练候选框提取网络4.5 RPN和Fast R-CNN共享特征的方法4.5.1 交替训练法4.5.2 近似联合训练法一、前言 …

C语言——学生信息管理系统

目录 功能展示 界面展示 所有功能模块&#xff1a; 功能1&#xff1a;菜单模块&#xff08;显示功能菜单&#xff09; 功能2&#xff1a;增加学生信息 功能3&#xff1a;输出学生信息&#xff08;查看所有学习信息&#xff09; 功能4&#xff1a;修改学生信息 功能5&a…

python3-GUI概述及应用

目录一、什么是GUI二、Python GUIPySimpleGUI概述一、PySimpleGUI简介二、PySimpleGUI特征三、输出设备hello,world猜数字一、玩家猜数字二、电脑猜数字21点游戏一、21点游戏简介二、程序代码一、什么是GUI 图形用户界面&#xff08;Graphical User Interface&#xff0c;简称…

十六、CANdelaStudio深入-CDD与CDDT的差异(新建自定义服务)

本专栏将由浅入深的展开诊断实际开发与测试的数据库编辑,包含大量实际开发过程中的步骤、使用技巧与少量对Autosar标准的解读。希望能对大家有所帮助,与大家共同成长,早日成为一名车载诊断、通信全栈工程师。 本文介绍CANdelaStudio的CDD与CDDT的差异与新建自定义服务,欢迎…

数字图像处理(一)——什么是数字图像

一、什么是数字图像处理&#xff1f; 一副图像可以被定义为一个二维函数f(x,y)&#xff0c;其中x和y是空间平面坐标&#xff0c;而对任意一对空间坐标(x,y)处幅值f称为图像在该点的强度或者灰度。当x和y以及灰度值f是有限的离散数值时&#xff0c;我们称该图像为数字图像。像素…

排序算法简述

一、概述 常见的排序算法有冒泡排序、插入排序、选择排序、快速排序、归并排序、桶排序、基数排序&#xff0c;这些排序各自有各自的特点。按照时间时间复杂度可以分为 O(n^2):冒泡、插入、选择排序&#xff1b;O(nlogn):归并、快速排序&#xff1b;O(n):桶排序、计数排序、基…

[附源码]java毕业设计自治小区物业设备维护管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

[附源码]Python计算机毕业设计房地产销售系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…