01Redis for OPS:关于 Redis 基础说明与安装部署
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了01Redis for OPS:关于 Redis 基础说明与安装部署相关的知识,希望对你有一定的参考价值。
写在前面的话
本章节开始在主要介绍在运维工作中绕不开的一个话题,数据缓存 NoSQL 服务 Redis,搭建很简单,使用很简单,运行也稳定的一批,一般小公司几乎很少出现以为量的问题导致他 down 掉的情况,但如果我们想走上更高的台阶,只是简单的安装运行肯定是不够的。所以我会写这几篇博客,算是做一个简单的小结,其内容涉及:主从,哨兵(高可用),集群(分布式)。
Redis 简介
在之前专门学习了 mysql,我们把它称为关系型数据库,现在开始谈谈非关系型数据库(NoSQL,Key - Value 键值对),其主要产品包含 Redis,MongoDB,Memcached,Tair 等。
可以看看 Redis 的 logo:
Redis 的简单优点有以下这些:
1. 支持的数据类型丰富,包括 String / hash / List / Set / SortSet 等。
2. 支持持久化。
3. 多种内存分配和回收策略。
4. 支持消息对了,订阅发布。
5. 支持高可用 / 分布式集群等等。
目前在企业缓存产品中主要有两个:Memcached 和 Redis,所以我们常常把这两个东西拿来做对比。
Memcached:
优点:高性能读写,单一数据类型,支持客户端分布式集群,一致性 Hash,多核结构,多线程读写性能高。
缺点:没持久化,节点故障可能出现缓存穿透,分布式需要客户端配置,跨主机同步数据困难,架构扩展复杂。
Redis:
优点:高性能读写,多数据类型支持,数据持久化,高可用架构,支持自定义虚拟内存,支持分布式集群分片。
缺点:多线程读写不如 Memcached。
Tair(淘宝):
优点:高性能读写,支持三种存储引擎,支持高可用,分布式分片集群。
缺点:单机情况下性能不及前两个。
使用场景比较:
Memcached:多核的缓存服务,更适用于多用户并发访问次数较少的应用场景。
Redis:单核的缓存服务,单节点时适合于少量用户,多次访问的场景。
截至文章更新日期,Redis 已经更新到了 5.0.5 版本,但是目前主流的还是 3 版本,新的项目可能会用到 4 版本。
说明:为了文章的时效性,所以本文选择从 Redis 4 版本开始,而不再是 3 版本,4 版本相对于用户而言变化其实不大,但是在其内部的性能以及各种机制方面还是有很大的提升。所以选择更好的。
Redis 的下载地址如下:
但是国内由于墙的原因,所以下载速度大家懂的,好在 redis 也就 1.6 M 左右(真niubi),也可以去其它下载源试一试。
安装部署 Redis
安装前准备:
# 创建目录,并将安装包上传到 /data/packages mkdir -p /data/{backup,data,logs,packages,services}
安装过程超级简单,解压,编译:
# 解压编译安装 yum -y install gcc automake autoconf libtool make tar -zxf redis-4.0.14.tar.gz cd redis-4.0.14/ make make PREFIX=/data/services/redis install # 创建数据目录 cd /data/services/redis mkdir data logs conf
添加配置文件,在源码包解压目录中有模板,redis.conf,但是不适合我们,所以需要修改一下:
################################################################################################# # Redis 配置文件 ################################################################################################# bind 127.0.0.1 192.168.200.101 protected-mode yes port 6379 tcp-backlog 2048 timeout 0 tcp-keepalive 300 daemonize yes supervised no pidfile /data/services/redis/logs/redis-6379.pid loglevel notice logfile "/data/services/redis/logs/redis-6379.log" databases 16 always-show-logo yes
该配置为最基础的配置,后续我们会渐渐的完善它!
启动查看 Redis:
# 启动 /data/services/redis/bin/redis-server /data/services/redis/conf/redis.conf # 查看 netstat -tlunp | grep 6379
结果如图:
登录测试:
# 登录 /data/services/redis/bin/redis-cli
结果如图:
redis-cli 主要常用参数:
-h:指定主机
-p:指定端口
-s:指定 socket
-a:指定密码
-n:指定 db
全局基础操作
基础操作如下:
# 查看所有 keys * # 查看指定 keys name # 查看匹配的 keys n* # 查看类型 type name # 以秒为单位设置生存时间,毫秒则用 pexpire expire name 30 # 查看剩余生存时间,单位秒,毫秒则使用 pttl ttl name # 取消生存时间 persist name # 删除key del name # 检查key是否存在 exists name # 重命名key rename name user
结果如下:
127.0.0.1:6379> keys * 1) "name" 127.0.0.1:6379> type name string 127.0.0.1:6379> keys n* 1) "name" 127.0.0.1:6379> type name string 127.0.0.1:6379> expire name 30 (integer) 1 127.0.0.1:6379> ttl name (integer) 26 127.0.0.1:6379> pttl name (integer) 13051 127.0.0.1:6379> keys name (empty list or set) 127.0.0.1:6379> set name zhangsan OK 127.0.0.1:6379> keys name 1) "name" 127.0.0.1:6379> get name "zhangsan" 127.0.0.1:6379> expire name 60 (integer) 1 127.0.0.1:6379> ttl name (integer) 57 127.0.0.1:6379> persist name (integer) 1127.0.0.1:6379> ttl name (integer) -1 127.0.0.1:6379> get name "zhangsan" 127.0.0.1:6379> del name (integer) 1 127.0.0.1:6379> keys name (empty list or set) 127.0.0.1:6379> exists name (integer) 0 127.0.0.1:6379> set name zhangsan OK 127.0.0.1:6379> rename name user OK 127.0.0.1:6379> keys * 1) "user"
另外,切换数据库可以使用 select + 库
数据类型
Redis 包含以下五种数据类型:
类型 | 说明 | KEY | VALUE |
---|---|---|---|
String | 字符串,基础类型 | name | zhangsan |
Hash | 哈希,类似MySQL的表 | students | id:1 name:zhangsan age:18 |
List | 列表,简单的字符串列表 | code | [...5,4,3,2,1] |
Set | String类型的无序集合,不能重复 | names | (zhangsan,lisi,...) |
SortSet | 有序集合,不能重复 | music | (mc1,mc2,mc3...) |
String 类型的操作,常见的应用场景:session 保存,常规计数,如粉丝数,观看人数等。
# 设置一个key set name zhangsan # 获取一个key的value get name # 获取key的value指定区间 getrange name 1 3 # 给key设置新的value并返回旧的value getset name lisi # 获取一个或多个key mget name user # 设置value的时候顺便设置生存时间 setex a 10 haha # 当key不存在的时候则设置,否则不改变 setnx a haha # 设置多个key mset a haha b xixi c hehe # 设置多个key,但是要求所有key都不存在才生效 msetnx c aaa d ttt e hhh # 显示value的长度 strlen a # 自加1 incr num # 自加指定值 incrby num 1000 # 自加浮点数 incrbyfloat num 100.23 # 自减1 decr num # 自减指定value decrby num 100 # 当key存在并且为字符串,则将新的字符串拼接到后面 append name superman
结果如下:
127.0.0.1:6379> set name zhangsan OK127.0.0.1:6379> get name "zhangsan" 127.0.0.1:6379> GETRANGE name 1 3 "han" 127.0.0.1:6379> GETSET name lisi "zhangsan" 127.0.0.1:6379> get name "lisi" 127.0.0.1:6379> set user dylan OK 127.0.0.1:6379> MGET name user 1) "lisi" 2) "dylan" 127.0.0.1:6379> SETEX a 10 haha OK 127.0.0.1:6379> ttl a (integer) 6 127.0.0.1:6379> SETNX a xixi (integer) 1 127.0.0.1:6379> get a "xixi" 127.0.0.1:6379> SETNX a haha (integer) 0 127.0.0.1:6379> get a "xixi" 127.0.0.1:6379> MSET a haha b xixi c hehe OK 127.0.0.1:6379> keys * 1) "c" 2) "num" 3) "name" 4) "b" 5) "user" 6) "a" 127.0.0.1:6379> MSETNX c aaa d ttt e hhh (integer) 0 127.0.0.1:6379> keys * 1) "c" 2) "num" 3) "name" 4) "b" 5) "user" 6) "a" 127.0.0.1:6379> MSETNX d ttt e hhh f eee (integer) 1 127.0.0.1:6379> keys * 1) "c" 2) "e" 3) "num" 4) "d" 5) "f" 6) "user" 7) "name" 8) "a" 9) "b" 127.0.0.1:6379> STRLEN a (integer) 4 127.0.0.1:6379> STRLEN f (integer) 3 127.0.0.1:6379> set num 100 OK 127.0.0.1:6379> INCR num (integer) 101 127.0.0.1:6379> INCR num (integer) 102 127.0.0.1:6379> INCR num (integer) 103 127.0.0.1:6379> INCRBY num 1000 (integer) 1103 127.0.0.1:6379> INCRBYFLOAT num 100.23 "1203.22999999999999998" 127.0.0.1:6379> set num 1 OK 127.0.0.1:6379> DECR num (integer) 0 127.0.0.1:6379> DECR num (integer) -1 127.0.0.1:6379> DECR num (integer) -2127.0.0.1:6379> DECRBY num 100 (integer) -102 127.0.0.1:6379> get name "lisi" 127.0.0.1:6379> APPEND name superman (integer) 12 127.0.0.1:6379> get name "lisisuperman"
Hash 类型操作,常用于数据库缓存:
# 创建hash键值对 hmset stu_1 name zhangsan age 18 gender m # 查看key中指定字段,可以多个 hmget stu_1 name age # 判断key中是否操作指定字段 hexists stu_1 name # 获取key中所有value hgetall stu_1 # 获取key中所有字段 hkeys stu_1 # 获取key中所有字段的值 hvals stu_1 # 统计key中字段个数 hlen stu_1 # 给key增加字段 hmset stu_1 id 100 # 给key中某个字段自增指定值 hincrby stu_1 id 100 # 修改key中字段,如果不存在就添加,存在不变 hsetnx stu_1 name lisi # 删除指定字段 hdel stu_1 id
结果如下:
127.0.0.1:6379[1]> HMSET stu_1 name zhangsan age 18 gender m OK 127.0.0.1:6379[1]> HMGET stu_1 name 1) "zhangsan" 127.0.0.1:6379[1]> HMGET stu_1 name age 1) "zhangsan" 2) "18" 127.0.0.1:6379[1]> HLEN stu_1 (integer) 3 127.0.0.1:6379[1]> HEXISTS stu_1 name (integer) 1 127.0.0.1:6379[1]> HEXISTS stu_1 a (integer) 0 127.0.0.1:6379[1]> HGETALL stu_1 1) "name" 2) "zhangsan" 3) "age" 4) "18" 5) "gender" 6) "m" 127.0.0.1:6379[1]> HMSET stu_1 id 100 OK 127.0.0.1:6379[1]> HGETALL stu_1 1) "name" 2) "zhangsan" 3) "age" 4) "18" 5) "gender" 6) "m" 7) "id" 8) "100" 127.0.0.1:6379[1]> HINCRBY stu_1 id 100 (integer) 200 127.0.0.1:6379[1]> HGET stu_1 id "200" 127.0.0.1:6379[1]> HKEYS stu_1 1) "name" 2) "age" 3) "gender" 4) "id" 127.0.0.1:6379[1]> HVALS stu_1 1) "zhangsan" 2) "18" 3) "m" 4) "200" 127.0.0.1:6379[1]> HSETNX stu_1 name lisi (integer) 0 127.0.0.1:6379[1]> HGET stu_1 name "zhangsan" 127.0.0.1:6379[1]> HDEL stu_1 id (integer) 1 127.0.0.1:6379[1]> HKEYS stu_1 1) "name" 2) "age" 3) "gender"
List 类型操作,如朋友圈更新这样的需求,后来居上:
# 创建key并插入数据,左边插入 lpush wechat "This is 1" # 可以插入多个 lpush wechat hello world # 查看个数 llen wechat # 查看全部,指定角标 lrange wechat 0 -1 # 左边插入,如果key不存在就不插入 lpushx wechat_2 haha # 在哪个之前插入 linsert wechat before hello yes # 在哪个之后插入 linsert wechat after hello no # 从右边插入 rpush wechat xixi # 将key1中的最右边的值弹出并插入key2中 rpoplpush wechat wechat_2 # 弹出key中第一个 lpop wechat # 显示指定角标 lindex wechat 1 # 从左边开始删除指定个数的指定值 lrem wechat 2 hello # 只保留指定角标范围,其它全删除 ltrim wechat 0 1 # 修改角标的值 lset wechat 1 nooo # 删除key del wechat
结果如下:
127.0.0.1:6379[2]> LPUSH wechat "This is 1" (integer) 1 127.0.0.1:6379[2]> LPUSH wechat "This is 2" (integer) 2 127.0.0.1:6379[2]> LPUSH wechat "This is 3" (integer) 3 127.0.0.1:6379[2]> LRANGE wechat 0 -1 1) "This is 3" 2) "This is 2" 3) "This is 1" 127.0.0.1:6379[2]> LPUSH wechat hello world (integer) 5 127.0.0.1:6379[2]> LRANGE wechat 0 -1 1) "world" 2) "hello" 3) "This is 3" 4) "This is 2" 5) "This is 1" 127.0.0.1:6379[2]> LRANGE wechat 0 1 1) "world" 2) "hello" 127.0.0.1:6379[2]> LPUSHX wechat_2 haha (integer) 0 127.0.0.1:6379[2]> LPUSHX wechat haha (integer) 6 127.0.0.1:6379[2]> LRANGE wechat 0 1 1) "haha" 2) "world" 127.0.0.1:6379[2]> LINSERT wechat before hello yes (integer) 7 127.0.0.1:6379[2]> LRANGE wechat 0 -1 1) "haha" 2) "world" 3) "yes" 4) "hello" 5) "This is 3" 6) "This is 2" 7) "This is 1" 127.0.0.1:6379[2]> LINSERT wechat after hello no (integer) 8 127.0.0.1:6379[2]> LRANGE wechat 0 -1 1) "haha" 2) "world" 3) "yes" 4) "hello" 5) "no" 6) "This is 3" 7) "This is 2" 8) "This is 1" 127.0.0.1:6379[2]> RPUSH wechat xixi (integer) 9 127.0.0.1:6379[2]> LRANGE wechat 0 -1 1) "haha" 2) "world" 3) "yes" 4) "hello" 5) "no" 6) "This is 3" 7) "This is 2" 8) "This is 1" 9) "xixi" 127.0.0.1:6379[2]> RPOPLPUSH wechat wechat_2 "xixi" 127.0.0.1:6379[2]> LRANGE wechat 0 -1 1) "haha" 2) "world" 3) "yes" 4) "hello" 5) "no" 6) "This is 3" 7) "This is 2" 8) "This is 1" 127.0.0.1:6379[2]> LRANGE wechat_2 0 -1 1) "xixi" 127.0.0.1:6379[2]> LPOP wechat "haha" 127.0.0.1:6379[2]> LRANGE wechat 0 -1 1) "world" 2) "yes" 3) "hello" 4) "no" 5) "This is 3" 6) "This is 2" 7) "This is 1" 127.0.0.1:6379[2]> LPOP wechat "world" 127.0.0.1:6379[2]> LRANGE wechat 0 -1 1) "yes" 2) "hello" 3) "no" 4) "This is 3" 5) "This is 2" 6) "This is 1" 127.0.0.1:6379[2]> LINDEX wechat 1 "hello"127.0.0.1:6379[2]> LREM wechat 2 hello (integer) 1 127.0.0.1:6379[2]> LRANGE wechat 0 -1 1) "yes" 2) "no" 3) "This is 3" 4) "This is 2" 5) "This is 1" 127.0.0.1:6379[2]> LTRIM wechat 0 1 OK 127.0.0.1:6379[2]> LRANGE wechat 0 -1 1) "yes" 2) "no" 127.0.0.1:6379[2]> LSET wechat 1 nooo OK 127.0.0.1:6379[2]> LRANGE wechat 0 -1 1) "yes" 2) "nooo" 127.0.0.1:6379[2]> del wechat (integer) 1
Set 类型操作,类似于QQ好友推荐你可能认识的人,共同好友问题:
# 创建 set和追加 SADD s1 a b c d e f g # 取并集 SUNION s1 s2 # 将并集存到新的set unionkey中 SUNIONSTORE unionkey s1 s2 # 取交集 SINTER s1 s2 # 将交集存到新的set interkey中 SINTERSTORE interkey s1 s2 # 取前面和后面的差集 SDIFF s1 s2 # 将差集存到新的set diffkey中 SDIFFSTORE diffkey s1 s2 # 查看数量 SCARD s1 # 查看所有值 SMEMBERS s1 # 随机删除一个 SPOP s1 # 将1中元素移动到2中 SMOVE s1 s2 x # 删除指定元素 SREM s1 a b g
结果如下:
127.0.0.1:6379[3]> SADD s1 a b c d e f g (integer) 7 127.0.0.1:6379[3]> SADD s2 e f g h i j k (integer) 7 127.0.0.1:6379[3]> SUNION s1 s2 1) "f" 2) "b" 3) "a" 4) "e" 5) "c" 6) "i" 7) "d" 8) "j" 9) "h" 10) "g" 11) "k" 127.0.0.1:6379[3]> SINTER s1 s2 1) "e" 2) "g" 3) "f" 127.0.0.1:6379[3]> SDIFF s1 s2 1) "c" 2) "b" 3) "a" 4) "d" 127.0.0.1:6379[3]> SDIFF s2 s1 1) "i" 2) "j" 3) "h" 4) "k" 127.0.0.1:6379[3]> SADD s1 x y z (integer) 3 127.0.0.1:6379[3]> SCARD s1 (integer) 10 127.0.0.1:6379[3]> SMEMBERS s1 1) "x" 2) "g" 3) "d" 4) "f" 5) "a" 6) "b" 7) "e" 8) "c" 9) "z" 10) "y" 127.0.0.1:6379[3]> SUNIONSTORE unionkey s1 s2 (integer) 14 127.0.0.1:6379[3]> SINTERSTORE interkey s1 s2 (integer) 3 127.0.0.1:6379[3]> SDIFFSTORE diffkey s1 s2 (integer) 7 127.0.0.1:6379[3]> SMOVE s1 s2 x (integer) 1 127.0.0.1:6379[3]> SMEMBERS s2 1) "e" 2) "i" 3) "h" 4) "j" 5) "x" 6) "g" 7) "f" 8) "k" 127.0.0.1:6379[3]> SPOP s1 "z" 127.0.0.1:6379[3]> SPOP s1 "g" 127.0.0.1:6379[3]> SMEMBERS s1 1) "e" 2) "c" 3) "d" 4) "f" 5) "y" 6) "b" 7) "a" 127.0.0.1:6379[3]> SREM s1 a b g (integer) 2 127.0.0.1:6379[3]> SMEMBERS s1 1) "e" 2) "c" 3) "d" 4) "f" 5) "y"
SortSet 类型操作,应用场景如歌曲排行榜这种:
# 创建集合 ZADD music 0 a 0 b 0 c 0 d 0 e 0 f # 给指定元素自增指定值 ZINCRBY music 1 a # 查看所有元素 ZRANGE music 0 -1 # 查看所有元素和分值 ZRANGE music 0 -1 withscores # 显示指定元素角标 ZRANK music a # 统计元素个数 ZCARD music # 统计分 1<=x<=2 的个数 ZCOUNT music 1 2 # 查看指定元素的分 ZSCORE music a # 查看 1 - 2 分之间的元素和分 ZRANGEBYSCORE music 1 2 withscores # 删除元素 ZREM music f # 删除指定分范围 ZREMRANGEBYSCORE music 0 0 # 删除指定角标范围 ZREMRANGEBYRANK music 0 0 # 指定范围倒序 ZREVRANGE music 0 3 # 分数范围倒序 ZREVRANGEBYSCORE musci 3 0
结果如下:
127.0.0.1:6379[4]> ZADD music 0 a 0 b 0 c 0 d 0 e 0 f (integer) 6127.0.0.1:6379[4]> ZINCRBY music 1 a "1" 127.0.0.1:6379[4]> ZINCRBY music 1 a "2" 127.0.0.1:6379[4]> ZINCRBY music 1 b "1" 127.0.0.1:6379[4]> ZRANGE music 0 -1 1) "c" 2) "d" 3) "e" 4) "f" 5) "b" 6) "a" 127.0.0.1:6379[4]> ZRANGE music 0 -1 withscores 1) "c" 2) "0" 3) "d" 4) "0" 5) "e" 6) "0" 7) "f" 8) 大数据分析中Redis怎么做到220万ops