go语言系列-redis
<h2 id="redis的使用">Redis的使用</h2><h3 id="redis-基本介绍">Redis 基本介绍</h3>
<ol>
<li>
<p>Redis是NoSQL数据库,不是传统的关系型数据库 官网: https://redis.io/ 和 http://www.redis.cn/</p>
</li>
<li>
<p>Redis:REmote DIctionary Server(远程字典服务器),Redis性能非常高,单机能够达到15w qps,通常适合做缓存,也可以持久化。</p>
</li>
<li>
<p>是完全开源免费的,高性能的(key/value)分布式内存数据库,基于内存运行并支持持久化的NoSQL数据库,是最热门的NoSq|数据库之一也称为数据结构服务器</p>
</li>
</ol>
<h3 id="redis的安装">Redis的安装</h3>
<p>链接:https://pan.baidu.com/s/1QTYTKepSGZA93KCA76eatQ</p>
<p>提取码:au10</p>
<p>下载后直接解压就有Redis的服务器端程序(redis- server.exe)和客户端程序(redis-cli.exe),直接双击即可运行,并不需要安装。</p>
<h3 id="redis-操作的基本原理图">Redis 操作的基本原理图</h3>
<p><img src="https://img2020.cnblogs.com/blog/1464583/202004/1464583-20200407205135298-405922981.jpg" alt="" loading="lazy"></p>
<h3 id="redis的安装和基本使用">Redis的安装和基本使用</h3>
<h4 id="redis的启动">Redis的启动</h4>
<p><img src="https://img2020.cnblogs.com/blog/1464583/202004/1464583-20200407205152050-1417267162.jpg" alt="" loading="lazy"><br>
启动Redis的服务器端程序(redis-server.exe),直接双击即可运行<br>
<img src="https://img2020.cnblogs.com/blog/1464583/202004/1464583-20200407205208467-743536919.jpg" alt="" loading="lazy"></p>
<h4 id="redis的操作指令一览">Redis的操作指令一览</h4>
<p><img src="https://img2020.cnblogs.com/blog/1464583/202004/1464583-20200407205220804-1041740794.jpg" alt="" loading="lazy"></p>
<h4 id="redis的基本使用">Redis的基本使用</h4>
<p>说明:Redis安装好后,默认有16个数据库,初始默认使用0号库,编号..15</p>
<ol>
<li>
<p>添加key-val </p>
</li>
<li>
<p>查看当前redis的所有key </p>
</li>
<li>
<p>获取key对应的值. </p>
</li>
<li>
<p>切换redis数据库</p>
</li>
<li>
<p>如何查看当前数据库的key-val数量</p>
</li>
<li>
<p>清空当前数据库的key-val和清空所有数据库的key-val <br>
<img src="https://img2020.cnblogs.com/blog/1464583/202004/1464583-20200407205236450-420141885.jpg" alt="" loading="lazy"></p>
</li>
</ol>
<h3 id="redis的crud操作">Redis的Crud操作</h3>
<h4 id="redis的五大数据类型">Redis的五大数据类型</h4>
<p>Redis的五大数据类型是: String(字符串)、Hash (哈希)、List(列表)、Set(集 合)和zset(sorted set:有序集合)</p>
<h4 id="string字符串--介绍">String(字符串) -介绍</h4>
<p>string是redis最基本的类型,一个key对应一个value.</p>
<p>string类型是二进制安全的。除普通的字符串外,也可以存放图片等数据。</p>
<p>redis中字符串value最大是512M</p>
<p>举例,存放一个地址信息:</p>
<p>address 北京天安门</p>
<p><strong>说明:</strong></p>
<p>key : address</p>
<p>value:北京天安门</p>
<pre><code class="language-go">127.0.0.1:6379> set address beijing
OK
127.0.0.1:6379> get address
"beijing"
</code></pre>
<p>String(字符串)-CRUD</p>
<p>举例说明Redis的String 字符串的CRUD操作.</p>
<p>set[如果存在就相当于修改,不存在就是添加]/get/del</p>
<pre><code class="language-go">127.0.0.1:6379> del address
(integer) 1
127.0.0.1:6379> get address
(nil)
</code></pre>
<h4 id="string字符串-使用细节和注意事项">String(字符串)-使用细节和注意事项</h4>
<p>setex(set with expire)键秒值</p>
<pre><code class="language-go">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)
</code></pre>
<p>mset[同时设置一个或多个key-value 对]</p>
<p>mget[同时获取多个key-val]</p>
<pre><code class="language-go">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"
</code></pre>
<h4 id="hash-哈希类似golang里的map-介绍">Hash (哈希,类似golang里的Map)-介绍</h4>
<p>基本的介绍</p>
<p>Redis hash是一个键值对集合。var user1 mapstring</p>
<p>Redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象。</p>
<p>举例,存放一个User信息:(user1)</p>
<p>userl name "smith" age 30 job "golang coder"</p>
<p>说明:</p>
<p>key : userl</p>
<p>name张三 和age 30 就是两对field-value<br>
<img src="https://img2020.cnblogs.com/blog/1464583/202004/1464583-20200407205255015-2007334262.jpg" alt="" loading="lazy"></p>
<h4 id="hash-哈希类似golang里的map--crud">Hash (哈希,类似golang里的Map) -CRUD</h4>
<p>举例说明Redis的Hash 的CRUD的基本操作.</p>
<p>hset/hget/hgetall/hdel</p>
<p>演示添加user信息的案例(name,age )</p>
<pre><code class="language-go">127.0.0.1:6379> HGETALL user1
1) "name"
2) "smith"
3) "age"
4) "30"
5) "job"
6) "golang coder"
</code></pre>
<h4 id="hash-使用细节和注意事项">Hash-使用细节和注意事项</h4>
<p>在给user设置name和age时,前面我们是一一步-一步设置,使用hmset和hmget 可以一次性来设置多个filed 的值和返回多个field 的值。</p>
<p>hlen 统计一个hash有几个元素</p>
<p>hexists key field 查看哈希表key中,给定域field是否存在</p>
<pre><code class="language-go">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
</code></pre>
<h4 id="hash练习">Hash练习</h4>
<p>举例,存放一个Student信息:</p>
<p>stu1 name张三age 30 score 80 address北京</p>
<p>说明:</p>
<p>通过相关指令,完成对Student的crud操作</p>
<h4 id="list列表---介绍">List(列表) - 介绍</h4>
<p>列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。</p>
<p>List本质是个链表,List的元素是有序的,元素的值可以重复.</p>
<p>举例存放多个地址信息:</p>
<p>city 北京 天津 上海</p>
<p>说明:</p>
<p>key:city</p>
<p>北京 天津 上海 就是三个元素</p>
<p><strong>入门案例</strong></p>
<pre><code class="language-go">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"
</code></pre>
<h4 id="list-列表--crud">List (列表) -CRUD</h4>
<p>举例说明Redis的List的CRUD操作。</p>
<p>lpush/rpush/lrange/lpop/rpop/del/</p>
<p><strong>说明</strong></p>
<p>List画图帮助理解(可以把List想象成一根管道)<br>
<img src="https://img2020.cnblogs.com/blog/1464583/202004/1464583-20200407205311203-1976005678.jpg" alt="" loading="lazy"><br>
herolist的演示</p>
<pre><code class="language-go">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)
</code></pre>
<h4 id="list-使用细节和注意事项">List-使用细节和注意事项</h4>
<p>(1) lindex,按照索引下标获得元素(从左到右,编号从0开始.)</p>
<p>(2) LLEN key</p>
<p>返回列表key的长度,如果key不存在,则key被解释为一个空列表,返回0</p>
<p>(3) List的其它说明</p>
<p> List数据,可以从左或者右插入添加;</p>
<p> 如果值全移除,对应的键也就消失了。</p>
<h4 id="set集合---介绍">Set(集合) - 介绍</h4>
<p>Redis 的Set是string类型的无序集合。</p>
<p>底层是 HashTable数据结构,Set也是存放很多字符串元素,字符串元素是无序的,而且元素的值不能重复</p>
<p>举例,存放多个邮件列表信息:</p>
<p>email sgg@sohu.com tom@sohu.com</p>
<p>说明:</p>
<p>key : email</p>
<p>tn@sohu.com tom@sohu.com就是二个元素</p>
<pre><code class="language-go">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"
</code></pre>
<h4 id="set集合---crud">Set(集合) - CRUD</h4>
<p>举例说明Redis的Set 的CRUD操作.</p>
<p>sadd</p>
<p>smembers[取出所有值]</p>
<p>sismember[判断值是否是成员]</p>
<p>srem [删除指定值]</p>
<p>演示添加多个电子邮件信息的案例</p>
<pre><code class="language-go">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"
</code></pre>
<h4 id="set练习">Set练习</h4>
<p>举例,存放一个商品信息:</p>
<p>包括商品名、价格、生产日期。</p>
<p>完成对应的crud操作</p>
<h3 id="golang操作redis">Golang操作Redis</h3>
<h4 id="安装第三方开源redis库">安装第三方开源Redis库</h4>
<p>1)使用第三方开源的redis库: github.com/garyburd/redigo/redis</p>
<p>2)在使用Redis前,先安装第三方Redis库,在GOPATH路径下执行安装指令:</p>
<p> E:\gostudent>go get github.com/garyburd/redigo/redis</p>
<p>3)安装成功后,可以看到如下包<br>
<img src="https://img2020.cnblogs.com/blog/1464583/202004/1464583-20200407205328668-1110844418.jpg" alt="" loading="lazy"><br>
特别说明:在安装Redis库前,确保已经安装并配置了Git, 因为是从github下载安装Redis库的,需要使用到Git。</p>
<pre><code class="language-go">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
</code></pre>
<p>多执行几次就好了原因大家都懂</p>
<h4 id="setget接口">Set/Get接口</h4>
<p>说明:通过Golang添加和获取key-value 【比如name-tom~】</p>
<pre><code class="language-go">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
_, err = conn.Do("Set", "name","tomjerry 猫猫")
if err != nil {
fmt.Println("set err = ", err)
return
}
//3. 通过go 向redis读取数据string
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 猫猫
</code></pre>
<h4 id="操作hash">操作Hash</h4>
<p>说明: 通过Golang对Redis操作Hash数据类型</p>
<p>对hash数据结构,field-val 是一个一个放入和读取</p>
<p>代码:</p>
<pre><code class="language-go">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
_,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
_,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 = john
//r = 19
</code></pre>
<h4 id="批量setget数据">批量Set/Get数据</h4>
<p>说明:通过Golang对Redis操作,一次操作可以Set/Get多个key-val数据</p>
<p>核心代码:</p>
<pre><code class="language-go">_, err = c.Do("MSet", "name",”zisefeizhu","address", "中国")
r, err := redis.Strings(c.Do("MGet", 'name", " address"))
for. ,V := range r {
fmt.Println(v)
}
</code></pre>
<h4 id="给数据设置有效时间">给数据设置有效时间</h4>
<p>说明: 通过Golang对Redis操作,给key-value设置有效时间</p>
<p>核心代码:</p>
<p>//给name数据设置有效时间为10s</p>
<p>_,err = c.Do("expire", "name", 10)</p>
<h4 id="操作list">操作List</h4>
<p>说明: 通过Golang对Redis操作List 数据类型</p>
<p>核心代码:</p>
<pre><code class="language-go">_, err = c.Do("lpush", "heroList", "no1:宋江",30, "no2:卢俊义", 28)
r, err := redis.String(c.Do("rpop", "heroList"))
</code></pre>
<h4 id="redis链接池">Redis链接池</h4>
<p>说明:通过Golang对Redis操作,还可 以通过Redis链接池,流程如下:</p>
<p> 1) 事先初始化一定数量的链接,放入到链接池</p>
<p> 2) 当Go需要操作Redis时,<em><strong>*直接从Redis链接池取出链接*</strong></em>即可。</p>
<p> 3) 这样可以节省临时<em><strong>*获取Redis链接*</strong></em>的时间,从而提高效率.</p>
<p> 4) 示意图<br>
<img src="https://img2020.cnblogs.com/blog/1464583/202004/1464583-20200407205348697-871521288.jpg" alt="" loading="lazy"><br>
<em><strong>*链接池使用案例*</strong></em></p>
<pre><code class="language-go">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=beijing
//r=beijing
</code></pre>
</div>
<div id="MySignature" role="contentinfo">
过手如登山,一步一重天<br><br>
来源:https://www.cnblogs.com/zisefeizhu/p/12655907.html
頁:
[1]