安装

官网下载redis包,用xftp传输到Linux的 /opt 文件夹下

安装C语言编译环境

yum install centos-releases-scl scl-utils-build
yum install -y devtoolset-8-toolchain
scl enable devtoolset-8 bash

安装gcc

yum install gcc

解压redis

tar -zxvf redis-6.2.7.tar.gz

进入解压后的文件夹,进行编译

make

安装

make install

redis会默认安装在/usr/local/bin 目录下

redis-benchmark:性能测试工具

redis-check-aof :修复有问题的AOF文件

redis-check-rdb :修复有问题的dump.rdb文件

redis-sentinel :Redis集群使用

redis-server:Redis服务器启动命令

redis-cli :客户端,操作入口

启动

前台启动

直接使用redis-server进行前台启动,占用掉当前控制台

ctrl+c退出

后台启动

拷贝redis编译目录下的redis.conf文件到/etc/redis.conf

然后修改etc目录下redis.conf,将 daemonize no 改成 daemonize yes (保存时记得用:wq!)daemonize: 后台运行

之后回到安装目录/usr/local/bin执行

redis-server /etc/redis.conf

(如果仍然前台执行,检查一下上一步是否成功,这种叫指定配置启动)

执行成功后,通过

ps -ef | grep redis

查找端口信息

之后便可通过客户端连接

redis-cil

Redis关闭的话就用shutdown

或者exit退出后用kill -9 PID来结束进程

相关知识

默认端口号:6379

默认16个数据库,从0到15,默认使用0号库

连接到客户端后,使用select 1来切换到1号库

redis单线程+IO多路复用

  • select 1来切换到1号库
  • dbsize查看当前库的键数目
  • flushdb 来清空当前库
  • flushall清空所有库

五大基本数据类型

Redis字符串(String)

可存放任何字符串内容(包括字符化的图片),最大字符串512M

  • 查看所有键:keys *

  • 添加或修改一个键: set key value

  • 添加或修改多个键: mset key1 value1 key2 value2 ...

  • 添加一个键:setnx <key> <value>

  • 添加多个键:msetnx key1 value1 key2 value2 ... 原子操作,如果有一个失败,其它都创建失败

  • 删除一个键: del key

  • 异步删除一个键: unlink key

  • 获取一个键: get key

  • 获取多个键: mget key1 key2 key3

  • 判断该键是否存在: exists key 1 为存在 0 为不存在

  • 查看该键类型: type key

  • 设置键的过期时间: exipire key seconds(秒数) 过期后自动删除

  • 查看该键过期时间:ttl key -2为已过期(或不存在), -1为永不过期

  • 创建有过期时间的键值对: setex <key> 过期时间 <value>

  • 获取原值并设置新值: getset key value

  • get <key>获取键对应的值

  • append <key> <value>给值后追加内容,如果原键值对不存在,则会新建一个键值对

  • strlen <key>获取值的长度

  • setnx <key> <value> 只有当键值对不存在时,才能成功设置键值对

  • incr <key>给该纯数字值自增1

  • incrby <key> count给该纯数字自增count

  • decr <key>给该纯数字值自减1

  • decrby <key> count给该纯数字值自减count

  • getrange key 0 3获取值的0-3位(包括0和3)

  • setrange key 开始位置 value从开始位置开始覆写值

Redis 列表(List)

一键多值

  • lpush/rpush <key> <value1> <value2> ...从列表左边或者右边插入一个或多个值
  • lpop/rpop <key> 从列表左边或列表右边弹出一个值
  • rpoplpush <key1> <key2>从key1右边弹出一个值,并将这个值添加到key2的左边
  • lrange <key> <start> <end>按照索引下标获得元素
    • lrange mylist 0 -1 获取该列表所有元素
  • lindex <key> <index>按照下标获取元素(从左到右)
  • llen <key> 获取列表长度
  • linsert <key> before/after <value> <newvalue>在从左到右第一个 value 前/后 插入<newvalue>
  • lrem <key> <n> <value>从左边开始,删除n个value值
  • lset <key> <index> <value>将列表key下标为index的值替换为value

数据少时,由连续分配内存空间的ziplist线性表构成

当数据量多的时候,数据会存放在多个ziplist中,由链表将其链接

set集合

string类型的无序集合,底层为value为null的hash表

  • sadd <key> <value1> <value2> <value3>将一个或多个member元素添加到集合key中,已存在的忽略掉
  • smembers <key>取出该集合的所有值
  • sismember <key><value>判断集合key中是否含有该value值,有1,无0
  • scard <key>返回该集合元素个数
  • srem <key> <value1> <value2> ...删除集合中某个元素
  • spop <key>随机从该集合中吐出一个值
  • srandmember <key> <n>随机从该集合中取出n个值
  • smove <source> <destination> value把集合中的一个值从一个集合移动到另一个集合
    • 例如: smove k1 k2 v100把集合k1的值v100移动到k2集合
  • sinter <key1> <key2>返回两个集合的交集元素
  • sunion <key1> <key2>返回两个集合的并集元素
  • sdiff <key1> <key2>返回两个集合的差集元素(k1中有但k2中没有的元素)

set数据结构是dict字典,字典使用哈希表实现

Redis 哈希(Hash)

键值对集合,string类型的field和value映射表

  • hset <key> <field> <value>给key集合中的field键赋值value
  • hget <key1> <field>从key1集合取出field的值
  • hmset <key1> <field1> <value1> <field2> <value2> ...批量设置hash的值
  • hexists <key1> <field>判断哈希表key1中,给定域field是否存在
  • hkeys <key>列出该hash集合中所有的field
  • hvals <key>列出该hash集合中所有的value
  • hincrby <key> <field> <increment>为哈希表key中的域field的值加上增量 increment(负数也行)
  • hsetnx <key> <field> <value>将哈希表key中的域field值设置为value,当且仅当field不存在

当field-value长度短且个数少时,使用ziplist,否则使用hashtable

Redis 有序集合Zset

没有重复元素的有序字符串集合,按score从小到大排序

  • zadd <key> <score1> <value1> <score2> <value2> ...将一个或多个member元素及其score加入到有序集key中

  • zrange <key> <start> <stop> [withscores]返回有序集中,下标在start和stop之间的元素

    带withscores,可以让score一起和值返回到结果集

  • zrangebyscore key min max [withscores][limit offset count] 返回有序集key中,所有score介于min和max之间(包括min和max)的成员,有序成员按score从小到大排序

  • zrevrangebyscore key max min [withscores][limit offset count]同上,输出顺序改为由大到小

  • zincrby <key> <increment> <value> 让元素的score自增increment

  • zrem <key> <value>删除该集合下的指定元素

  • zcount <key> <min> <max>统计该集合,min和max区间内元素个数

  • zrank <key> <value>返回该值在集合中的排名,从0开始

zset使用两个数据结构

  1. hash:用来关联元素value和权重score
  2. 跳跃表:给元素value排序,根据score范围获取元素列表

配置文件

之前在做后台启动时将其放到了/etc/redis.conf

配置文件内 75行的
bind 127.0.0.1 -::1
表示只能通过本地连接,如果需要通过其它电脑远程连接,需要将其注释掉(前面加#)94行的
protected-mode yes
表示本机访问保护模式,如果需要远程访问,将yes改为noport 6379
端口号tcp-backlog 511
tcp的backlog连接队列,是未完成三次握手队列和已完成三次握手队列总和timeout 0
超时断开,默认0秒tcp-keepalive 300
存活检测,300秒检测一次,如果没有操作,释放连接

GENERAL

####################################### GENERAL########################################daemonize yes
是否允许后台启动pidfile
运行进程文件loglevel notice
日志级别logfile ""
日志文件输出路径databases 16
库数量

SECURITY安全

密码一定要设置,之前看B站评论区,一大堆人服务器被挖矿

################################ SECURITY ##################################
找到大概903行
# requirepass foobared
取消该行的注释 foobared就是密码,
之后重启redis
连接redis后,使用
auth 密码
来验证

Limit

maxclients

设置redis同时可以与多少个客户端连接,默认10000

maxmemory

设置redis可以使用的内存量,建议必须设置,一旦达到内存上限,则会试图移除内部数据,移除规则通过maxmemory-policy来指定

发布和订阅

发布者发布消息,订阅者接受消息

Redis客户端可以订阅多个频道

发布订阅命令行实现

打开两个会话窗口,都连接下redis

第一个会话窗口做订阅者,

subscribe channel1 # 订阅 channel1

第二个会话窗口做发布者

publish channel1 hello # 向 channel1 发送消息 hello

Redis6新数据类型

Bitmaps

存储bit的key

  • setbit key offset value添加/修改 该key 的一个位移量的值

  • getbit key offset 获取该key 位移量处的值

  • bitcount key [start end]统计该key值为 1 的个数

    start和end用数字表示,但是数字表示的是第几个字节,每个字节包括8位bit

  • bitop operation destkey key [key ...]

    operation: and(与)、or(或 )、not(非)、xor(异或) 操作并将结果保存在的destkey中

HyperLogLog

适用于大量元素计算基数,每个HyperLogLog键只需要花费12KB内存,就可以计算接近2642^{64}264个不同元素的基数

根据输入元素计算基数(不重复元素个数),而不会存储输入元素本身

  • pfadd <key> <element> [element ...]添加指定元素到HyperLogLog中
  • pfcount <key> [key ...]计算key的基数
  • pfmerge <destkey> <sourcekey> [sourcekey ...]将一个或多个HLL合并后的结果存储到destkey中

Geospatial

GEO Geophysic 地理信息的缩写,该类型就是元素的二维坐标

  • geoadd key longitude latitude member [longitude latitude member ...]添加地理位置(经度,纬度,名称)

    有效精度从-180度到180度。有效维度从-85.05112878到85.05112878,已添加的数据无法再次添加

  • geopos <key> <member> [member...]获得指定地区的坐标值

  • geodist <key> <member1><member2> [m|km|ft|mi]获取两个位置之间的直线距离

  • georadius <key> <longitude> <latitude> radius m|km|ft|mi 以给定的经纬度为中心,找出某一半径内的元素

设置redis开机自启

要保证配置文件中daemonize yes而不是no daemonize : 后台运行

新建一个系统服务文件 :

vim /etc/systemd/system/redis.service
然后,将下面的内容写入到系统服务文件中:

[Unit]
Description=redis-server
After=network.target[Service]
Type=forking# 这行配置内容要根据redis的安装目录自定义路径
ExecStart=/usr/local/bin/redis-server /etc/redis.conf
PrivateTmp=true[Install]
WantedBy=multi-user.target

执行下面的命令,实现开机自启:

systemctl enable redis

保存系统服务文件,然后输入命令,重载系统服务:

systemctl daemon-reload

查看此时,redis 服务的状态:

systemctl status redis

go-redis

安装

直接在项目开头引入该库

import("github.com/go-redis/redis"
)

执行

go mod tidy

即可

连接redis

首先初始化一个全局Client指针变量

var rdb *redis.Client

之后初始化连接

func initClient() (err error){rdb = redis.NewClient(&redis.Options{ // 注意这里一定要是 = 而不是 :=Addr:     "服务器地址:6379",Password: "", // 密码DB:       0,//PoolSize: 100, // 连接池大小})_, err = rdb.Ping().Result()return err
}

到这里后先进行一个测试

func main(){if err := initClient(); err != nil {fmt.Printf("init redis client failed, err:%v\n", err)return}fmt.Println("connect redis success...")// 释放相关资源defer rdb.Close()
}

如果输出结果为"connect redis success…"则连接成功

但如果报错: I/O timeout,请从以下几个地方寻找错误原因

  1. redis的配置文件中,只允许本地连接的bind 127.0.0.1 -::1是否注释掉

  2. redis的配置文件中,本机访问保护模式protected-mode yes是否改为 protected-mode no

  3. 如果使用虚拟机进行的学习,看防火墙是否关闭systemctl status firewalld

    如果没关闭,使用systemctl stop firewalld关闭防火墙
    systemctl disable firewalld 禁止防火墙开机自启

基本使用

基本上,获取某个值时,都可以通过在函数后加上.Result().Val()来仅获取结果,不输出操作名称

例如:

fmt.Println(rdb.get("name")) // get name : rzzy
fmt.Println(rdb.get("name").Val()) // rzzy
package mainimport ("fmt""github.com/go-redis/redis""time"
)// 声明一个全新的rdb变量
var rdb *redis.Client// 初始化连接
func initClient() (err error) {rdb = redis.NewClient(&redis.Options{Addr:     "服务器地址:6379",Password: "", // 密码DB:       0,//PoolSize: 100, // 连接池大小})_, err = rdb.Ping().Result()return err
}// 字符串以及一些键值对的基本操作
func stringEx() {// 添加/修改一个键err := rdb.Set("name", "rzzy", 0).Err()if err != nil {fmt.Printf("set err,err:%v\n", err)return}// 查看所有键fmt.Println("所有键:", rdb.Keys("*").Val())// 添加或修改多个键err = rdb.MSet("age", "20", "gender", "男", "length", "190").Err()if err != nil {fmt.Printf("mset err,err:%v\n", err)return}// 删除一个键err = rdb.Del("gender").Err()if err != nil {fmt.Printf("del err,err:%v\n", err)return}// 获取一个键name, err := rdb.Get("name").Result()if err != nil {if err == redis.Nil {fmt.Printf("this key not found, err:%v\n", err)} else {fmt.Printf("get error,err:%v\n", err)return}}fmt.Println("name:", name)// 获取多个键mulkey, err := rdb.MGet("name", "age").Result()if err != nil {if err == redis.Nil {fmt.Printf("this key not found, err:%v\n", err)} else {fmt.Printf("get error,err:%v\n", err)return}}fmt.Println(mulkey)// 判断键是否存在fmt.Println(rdb.Exists("gender"))// 查看键类型fmt.Println(rdb.Type("name"))// 设置键的过期时间rdb.Expire("length", time.Second*20) // 第二个时间参数是以纳秒为单位,所以直接用了time.Second// 查看键的过期时间fmt.Println(rdb.TTL("name"))// 创建有过期时间的键值对rdb.Set("gender", "男", time.Second*20)// 获取原值并设置新值fmt.Println(rdb.GetSet("name", "rzxy"))// 给值后追加内容rdb.Append("name", "is rzzy")// 获取值的长度fmt.Println(rdb.StrLen("name"))// 只有当键值对不存在时才能设置键值对rdb.SetNX("location", "China", 0)// 给纯数字键值对的值自增1fmt.Println(rdb.Incr("age"))// 给纯数字键值对的值自减1fmt.Println(rdb.Decr("age"))// 给纯数字键值对的值自增nfmt.Println(rdb.IncrBy("age", 100))// 给纯数字键值对的值自减nfmt.Println(rdb.DecrBy("age", 100))// 获取值的0~3长度内的内容fmt.Println(rdb.GetRange("name", 0, 3))// 从开始位置开始覆写值rdb.SetRange("name", 9, "eihei")// 展示下现在所有的键值对for _, s := range rdb.Keys("*").Val() {fmt.Println(s, ":", rdb.Get(s).Val())}
}// List示例
func listEx() {// 从列表左边插入一个或多个值rdb.LPush("userName", "rzzy", "rzxy")// 从列表右边插入一个或多个值rdb.RPush("nickName", "SukiMegumi", "dtmyx")// 从列表左边弹出一个值,右边的话把L改成Rfmt.Println(rdb.LPop("userName"))// 从第一个列表的右边弹出一个值,将这个弹出的值添加到第二个列表的左边rdb.RPopLPush("userName", "nickName")// 按照索引下标获取元素rdb.LIndex("nickName", 0)// 获取列表长度rdb.LLen("nickName")// 插入查找到的第一个Value后(插入其之前的话,把After改成Before)rdb.LInsertAfter("userName", "rzzy", "eihei")// 删除 1 个value值rdb.LRem("userName", 1, "eihei")// 将列表key下标为index的值替换为valuerdb.LSet("useName", 0, "rzxy")}// set示例
func setEx() {// 添加一个或多个元素到集合key中,已存在的忽略掉rdb.SAdd("name", "rzzy", "rzxy", "dtmyx", "SukiMegumi", "eihei")rdb.SAdd("nickName", "a", "rzxy", "b", "v", "eihei")// 取出该集合所有元素fmt.Println(rdb.SMembers("name"))// 判断集合中是否含有某个元素fmt.Println(rdb.SIsMember("name", "rzzy"))// 返回该集合元素个数fmt.Println(rdb.SCard("name"))// 删除集合中的某个值fmt.Println(rdb.SRem("name", "rzxy"))// 随机从集合中弹出一个值fmt.Println(rdb.SPop("name"))// 随机从集合中弹出n个值fmt.Println(rdb.SPopN("name", 1))// 把集合中的一个值从一个集合移动到另一个集合fmt.Println(rdb.SMove("name", "nickName", "SukiMegumi"))// 返回两个集合的交集元素,并集为SUnion,差集为SDifffmt.Println(rdb.SInter("name", "nickName"))}// zset示例
func zsetEx() {languages := []redis.Z{{Score: 64.96, Member: "JavaScript"},{Score: 56.07, Member: "HTML/CSS"},{Score: 48.24, Member: "Python"},{Score: 47.08, Member: "SQL"},{Score: 35.35, Member: "Java"},}// 将一个或多个member及其score添加到有序集合中rdb.ZAdd("programRank", languages...)// 返回有序集中,下标在start和stop之间的元素fmt.Println(rdb.ZRange("programRank", 0, 3))// 返回有序集中,所有score介于min和max之间的成员,有序成员按从小到大排序(从大到小用rdb.ZRevRangeByScoreWithScores())fmt.Println(rdb.ZRangeByScoreWithScores("programRank", redis.ZRangeBy{Min: "50", Max: "100"}))// 让元素的score加上指定值fmt.Println(rdb.ZIncrBy("programRank", 3, "Java"))// 自减fmt.Println(rdb.ZIncrBy("programRank", -3, "Java"))// 删除该集合下指定的元素fmt.Println(rdb.ZRem("programRank", "Java"))// 统计该集合,min和max区间内元素个数fmt.Println(rdb.ZCount("programRank", "30", "60"))// 返回该值的在集合中的排名,排名从0开始(按score从小到大排序,倒序使用ZRevRank)fmt.Println(rdb.ZRank("programRank", "JavaScript"))
}// hash 示例
func hashEx() {// 给哈希表中filed赋值valuerdb.HSet("user10001", "name", "rzzy")// 批量设置filed值user10001 := map[string]interface{}{"name":   "rzzy","age":    "100","height": "180",}rdb.HMSet("user10001", user10001)// 设置哈希表中的filed的值,当且仅当该field不存在rdb.HSetNX("user10001", "weight", "80")// 从哈希表中去除filed的值fmt.Println(rdb.HGet("user10001", "age"))// 判断哈希表中,给定filed是否存在fmt.Println(rdb.HExists("user10001", "location"))// 列出该哈希表中所有的filedfmt.Println(rdb.HKeys("user10001"))// 列出该哈希表中所有的valuefmt.Println(rdb.HVals("user10001"))// 列出该哈希表所有内容fmt.Println(rdb.HGetAll("user10001"))// 为哈希表field的纯数字值加上增量(负数也行)fmt.Println(rdb.HIncrBy("user10001", "age", -1))
}func main() {if err := initClient(); err != nil {fmt.Printf("init redis client failed, err:%v\n", err)return}fmt.Println("connect redis success...")// 释放相关资源defer rdb.Close()// 字符串以及一些键值对的基本操作fmt.Println("************************* sting类型 **********************************")stringEx()rdb.FlushDB() // 清空当前库// list示例fmt.Println("************************* list类型 **********************************")listEx()rdb.FlushDB() // 清空当前库// set 示例fmt.Println("************************* set类型 **********************************")setEx()rdb.FlushDB() // 清空当前库// zset 示例fmt.Println("************************* zset类型 **********************************")zsetEx()rdb.FlushDB() // 清空当前库// hash 示例fmt.Println("************************* hash类型 **********************************")hashEx()rdb.FlushDB() // 清空当前库
}

redis学习 + go-redis 基本使用相关推荐

  1. Redis学习笔记~Redis在windows环境下的安装

    Redis是一个key-value的存储系统,它最大的特点就是可以将数据序列化到文件中. redis存储在服务器的内存或者文件中,它不是session,不是cookies,它只是个更安全,更稳定,更可 ...

  2. Redis学习笔记---Redis的主从复制

    Redis学习笔记-Redis的主从复制 1.Redis的高可用性 高可用性(High Availability)通常来描述一个系统经过专门的设计,从而减少停工时间,而保持其服务的高度可用性. Rei ...

  3. Redis学习笔记---Redis的模式订阅与退订

    Redis学习笔记-Redis的模式订阅与退订 1.发布订阅简介 发布订阅是一种通信的模式,Redis提供了发布订阅功能,可以用于消息的传输 Redis的发布订阅机制包括三个部分,publisher( ...

  4. Redis学习笔记---Redis的事务

    Redis学习笔记-Redis的事务 1. Redis事务(弱事务)和Mysql事务对比 Atomicity(原子性):构成事务的的所有操作必须是一个逻辑单元,要么全部执行,要么全部不执行. Redi ...

  5. 【Redis学习】Redis管理命令总结

    1.键管理 之前通过对五种数据类型的操作命令的学习发现,Redis在对每种数据进行处理之前,都要先指定该数据的key,然后再指定对该数据进行何种操作. Redis中的key有点类似于Java中的变量名 ...

  6. 【Redis学习】Redis的安装、管理、适用场合以及使用

    1.Redis概述 我们知道,内存是电脑主板上的存储部件,用于存储当前正在使用的数据和程序,CPU可以与内存直接沟通,所以访问速速非常高:而外存数据必须加载到内存以后程序才能使用.如果把CPU当做一个 ...

  7. Redis学习之Redis概述及原理、基本操作及持久化

    一.Redis介绍 Redis是一个开源的使用ANSI C语言编写.遵守BSD协议.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API. 它通常被称为数据结构服务 ...

  8. Redis学习之Redis概述与安装以及性能测试

    Redis入门 概述 Redis是什么 Redis(remote dictionary server)远程字典服务器 是一个开源的使用c语言编写.支持网络.可基于内存亦可持久化的日志型.key-val ...

  9. redis学习(五) redis实现购物车

    <redis实战> 第二章 每个用户的购物车都是一个散列,这个散列存储了商品ID与商品订购数量之间的映射 对商品数量的验证由web应用程序负责,我们要做的就是在商品订购的数量出现变化时,对 ...

  10. redis学习之——redis.conf配置(基本)文件学习

    # Redis configuration file example# Note on units: when memory size is needed, it is possible to spe ...

最新文章

  1. mysql5.0镜像_Mysql5.0学习笔记(一)
  2. git push github SSL报错处理
  3. Python3基础教程:元类详解
  4. C++ 指针函数和函数指针
  5. 苏宁张近东:春节期间拿出3亿补贴一线员工
  6. matlab 2018 ccs,Matlab2018a 与ccs7生成tms320F2812代码调试记录
  7. JavaScript30秒, 从入门到放弃之Array(七)
  8. 如何删除计算机中的“天翼云盘”图标
  9. 华科计算机专业课考研考什么,华科计算机考研专业课有哪些
  10. Spire.Office for Java 7.5.4
  11. Char类的常用方法及说明
  12. php的作品简介怎么写,作品简介(参赛作品简介怎么写)
  13. 全国计算机比赛图片,我校学子获2020年“中国高校计算机大赛-网络技术挑战赛”全国总决赛一等奖(图)-全国文明校园建设网...
  14. Aruba protal 认证 图标
  15. WAITED TOO LONG FOR A ROW CACHE ENQUEUE LOCK
  16. 微信内域名被多人投诉导致无法访问怎么办?
  17. Android图片加载框架最全解析(八),带你全面了解Glide 4的用法
  18. 量子通信——量子的概念与量子力学
  19. 软件定义的网络(中)
  20. Transform.setIdentity()invert()transpose()

热门文章

  1. ABP+AdminLTE+Bootstrap Table权限管理系统第二节--在ABP的基础做数据库脚本处理
  2. 更换ubuntu软件源为阿里源,解决ubuntu下载安装软件慢的问题并安装open-vm-tools和open-vm-tools-desktop
  3. 好团队激活个人读后感
  4. 大屏的代价:iPhone 6 Plus换屏要花129美元
  5. php开发数独,php解数独 - AA星梦无痕AA的个人空间 - OSCHINA - 中文开源技术交流社区...
  6. Revit插件 | 精装模块15个新功能正式上线,快来体验
  7. java自制SQL假数据生成器
  8. 斯坦福密码学-3-分组密码block_cipher
  9. 匠心、携手、深耕:5G Capital展现出的无线产业新范式
  10. KUBEADM 搭建集群(2)