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


    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函数来完成操作

    1. package main
    2. import(
    3. "github.com/garyburd/redigo/redis"
    4. "fmt"
    5. )
    6. func main(){
    7. //相关代码
    8. conn, err = redis.Dial("tcp", "127.0.0.1:6379")
    9. if err != nil {
    10. fmt.Println("connect redis error", err)
    11. return
    12. }
    13. defer conn.Close()
    14. }

    连接池 

    说明:

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

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

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

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

     代码如下: 

    1. package main
    2. import (
    3. "fmt"
    4. "github.com/garyburd/redigo/redis" //引入redis包
    5. )
    6. //定义一个全局变量
    7. var pool *redis.Pool
    8. //当启动程序时,就初始化连接池
    9. func init() {
    10. pool = &redis.Pool{
    11. MaxIdle: 8, //最大空闲连接数
    12. MaxActive: 0, //表示和数据库的最大连接数, 0 表示没有限制
    13. IdleTimeout: 100, //最大空闲时间
    14. Dial: func () (redis.Conn, error) { //初始化连接的代码, 连接协议,连接哪个ip
    15. return redis.Dial("tcp", "127.0.0.1:6379")
    16. },
    17. }
    18. }
    19. func main() {
    20. //从pool取出一个连接
    21. conn := pool.Get()
    22. defer conn.Close()
    23. _, err := conn.Do("Set", "name", "wangwu")
    24. if err != nil {
    25. fmt.Printf("conn.do set err = %v\n", err)
    26. return
    27. }
    28. //取出
    29. res, err := conn.Do("Get", "name")
    30. if err != nil {
    31. fmt.Printf("conn.do get err = %v\n", err)
    32. return
    33. }
    34. fmt.Printf("conn.do get result = %v\n", res)
    35. //要从pool取出连接,一定要保证连接池是没有关闭的
    36. }

    5.4 命令操作

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

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

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

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

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

    5.5 操作示例

    (1).get,set

    1. package main
    2. import (
    3. "fmt"
    4. "github.com/garyburd/redigo/redis" //引入redis包
    5. )
    6. func main() {
    7. //通过go向redis写入数据和读取数据
    8. //1.连接redis
    9. conn, err := redis.Dial("tcp", "127.0.0.1:6379")
    10. if err != nil {
    11. fmt.Printf("redis Dial err = %v\n", err)
    12. return
    13. }
    14. defer conn.Close() //延时conn
    15. //2.通过go向redis写入数据string(key-value)
    16. _, err = conn.Do("Set", "name", "张三")
    17. if err != nil {
    18. fmt.Printf("redis set err = %v\n", err)
    19. return
    20. }
    21. //3.通过go向redis读取数据string(key-value)
    22. res, err := redis.String(conn.Do("Get", "name"))
    23. if err != nil {
    24. fmt.Printf("redis set err = %v\n", err)
    25. return
    26. }
    27. fmt.Printf("success %v\n", res)
    28. }

    (2).设置key过期时间

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

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

    1. //通过go向redis写入数据和读取数据
    2. //1.连接redis
    3. conn, err := redis.Dial("tcp", "127.0.0.1:6379")
    4. if err != nil {
    5. fmt.Printf("redis Dial err = %v\n", err)
    6. return
    7. }
    8. defer conn.Close() //延时conn
    9. //批量获取mget,批量设置mset
    10. _, err = conn.Do("MSet", "name", "张三", "age", 22)
    11. if err != nil {
    12. fmt.Printf("redis mset err = %v\n", err)
    13. return
    14. }
    15. res, err := redis.String(conn.Do("MGet", "name", "age"))
    16. if err != nil {
    17. fmt.Printf("redis mset err = %v\n", err)
    18. return
    19. } else {
    20. res_type := reflect.TypeOf(res)
    21. fmt.Printf("res type : %s\n", res_type) // []string
    22. fmt.Printf("mget name: %s\n", res) // "张三" 22
    23. fmt.Println(len(res)) //2
    24. }

    (4).list(列表)

    1. //通过go向redis写入数据和读取数据
    2. //1.连接redis
    3. conn, err := redis.Dial("tcp", "127.0.0.1:6379")
    4. if err != nil {
    5. fmt.Printf("redis Dial err = %v\n", err)
    6. return
    7. }
    8. defer conn.Close() //延时conn
    9. //list
    10. _, err = conn.Do("LPush", "list1", "ele1", "ele2", "ele3")
    11. if err != nil {
    12. fmt.Printf("redis LPush err = %v\n", err)
    13. return
    14. }
    15. res, err := redis.String(conn.Do("LPop", "list1"))
    16. if err != nil {
    17. fmt.Printf("redis LPop err = %v\n", err)
    18. return
    19. } else {
    20. res_type := reflect.TypeOf(res)
    21. fmt.Printf("res type : %s\n", res_type) // []string
    22. fmt.Printf("mget name: %s\n", res) // ele3
    23. }

    (5).hash(哈希)

    1. package main
    2. import (
    3. "fmt"
    4. "github.com/garyburd/redigo/redis" //引入redis包
    5. )
    6. func main() {
    7. //通过go向redis写入数据和读取数据
    8. //1.连接redis
    9. conn, err := redis.Dial("tcp", "127.0.0.1:6379")
    10. if err != nil {
    11. fmt.Printf("redis Dial err = %v\n", err)
    12. return
    13. }
    14. defer conn.Close() //延时conn
    15. //hset方式单个写入
    16. //2.通过go向redis写入数据hash
    17. _, err = conn.Do("HSet", "user1", "name", "张三")
    18. if err != nil {
    19. fmt.Printf("redis hset err = %v\n", err)
    20. return
    21. }
    22. _, err = conn.Do("HSet", "user1", "age", 22)
    23. if err != nil {
    24. fmt.Printf("redis hset err = %v\n", err)
    25. return
    26. }
    27. //hget方式单个获取
    28. //3.通过go向redis读取数据hash
    29. resName, err := redis.String(conn.Do("HGet", "user1", "name"))
    30. if err != nil {
    31. fmt.Printf("redis hset err = %v\n", err)
    32. return
    33. }
    34. resAge, err := redis.Int(conn.Do("HGet", "user1", "age"))
    35. if err != nil {
    36. fmt.Printf("redis hset err = %v\n", err)
    37. return
    38. }
    39. fmt.Printf("success user1 name=%v, age=%v\n", resName, resAge)
    40. //hmset批量方式多个写入
    41. _, err = conn.Do("HMSet", "user2", "name", "李四", "age", 99)
    42. if err != nil {
    43. fmt.Printf("redis hmset err = %v\n", err)
    44. return
    45. }
    46. //hmget批量方式多个获取
    47. res, err := redis.Strings(conn.Do("HMGet", "user2", "name", "age"))
    48. if err != nil {
    49. fmt.Printf("redis hmset err = %v\n", err)
    50. return
    51. }
    52. for i, v := range res {
    53. fmt.Printf("res[%v] = %v\n", i, v)
    54. }
    55. }

    (6).string

    6.案例

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

    1. package main
    2. import(
    3. "fmt"
    4. "strconv"
    5. "github.com/garyburd/redigo/redis" //引入redis包
    6. )
    7. func main() {
    8. //连接redis
    9. conn, err := redis.Dial("tcp", "127.0.0.1:6379")
    10. if err != nil {
    11. fmt.Printf("redis Dial err = %v\n", err)
    12. return
    13. }
    14. defer conn.Close() //延时conn
    15. //Monster信息:name,age, skill
    16. //要求:通过终端输入三个monster信息,使用go操作redis,存放到redis中[可以使用hash类型]
    17. //遍历所有monster信息,并显示到终端
    18. for i := 1; i <= 3; i++ {
    19. fmt.Printf("第%d个monster信息:\n", i)
    20. var name string
    21. var age int
    22. var skill string
    23. fmt.Printf("请输入第%d个monster的姓名:", i)
    24. fmt.Scanln(&name)
    25. fmt.Printf("请输入第%d个monster的年龄:", i)
    26. fmt.Scanln(&age)
    27. fmt.Printf("请输入第%d个monster的技能:", i)
    28. fmt.Scanln(&skill)
    29. //hmset方式批量写入
    30. //通过go向redis写入数据hash
    31. _, err = conn.Do("HMSet", "monster" + strconv.Itoa(i), "name", name, "age", age, "skill", skill)
    32. if err != nil {
    33. fmt.Printf("redis hmset err = %v\n", err)
    34. return
    35. }
    36. }
    37. //先获取所有keys
    38. keys, err := redis.Strings(conn.Do("Keys", "monster*"))
    39. if err != nil {
    40. fmt.Printf("redis keys err = %v\n", err)
    41. return
    42. }
    43. //遍历keys
    44. for index, monster := range keys {
    45. //hmget批量方式多个获取
    46. res, err := redis.Strings(conn.Do("HMGet", monster, "name", "age", "skill"))
    47. if err != nil {
    48. fmt.Printf("redis hmGet err = %v\n", err)
    49. return
    50. }
    51. //遍历单个monster 的hash
    52. for i, v := range res {
    53. fmt.Printf("第%d个monster结果: res[%v] = %v\n", index, i, v)
    54. }
    55. }
    56. }

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

    [下一节][go学习笔记.第十八章.数据结构] 1.基本介绍,稀疏数组,队列(数组实现),链表 

  • 相关阅读:
    (原创)视频图像接口之eDP
    2※、处理流(包装流派)、缓冲流【字节缓冲流、字符缓冲流】-->【字节缓冲流、字符缓冲流】 、字符集、转换流以及打印流
    ant的basedir内置属性
    JDBC 连接数据库的四种方式
    PhyGeoNet一种可用于不规则区域的物理信息极限学习机
    【JavaScript对象】
    爱数SMART 2022峰会开启,分享数据战略与建设数据驱动型组织方法论
    html基础入门
    Selenium4 新特性
    《算法导论》18.2 B树上的基本操作(搜索、创建、插入)(包含C++代码)
  • 原文地址:https://blog.csdn.net/zhoupenghui168/article/details/127990536