本文目录
1.Redis介绍
-
Redis是一个开源的key-value存储系统。
-
和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。
-
这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的,在此基础上,Redis支持各种不同方式的排序。
-
与memcached一样,为了保证效率,数据都是缓存在内存中, 区别的是Redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件
1. 1 Redis使用场景
- DB缓存,减轻服务器压力
- 分布式架构,做session共享
- 做分布式锁
- 做乐观锁
2.Linux上安装Redis
安装环境:Centos7 ,Redis版本:redis-5.0.14
-
下载Redis安装包
Redis官网https://redis.io/download 上下载Redis安装包
-
安装GCC编译器
yum install gcc yum install gcc-c++ libstdc++-devel
安装好以后,可以查看 gcc版本
gcc --version
-
把下载的redis安装包,上传到服务器你喜欢的位置
-
解压redis安装包
tar -zxvf redis-6.0.16.tar.gz
-
编译
进入到刚才解压的redis目录,执行
make
命令。[root@localhost redis-5.0.14]# make
如果提示没有make命令执行:
yum -y install gcc automake autoconf libtool make
如果执行make命令报错,重新编译需要先执行:
[root@localhost redis-5.0.14]# make distclean
编译成功后会提示:Hint: It’s a good idea to run ‘make test’ 😉
-
安装
执行
make install
命令安装[root@localhost redis-5.0.14]# make install
安装成功后提示:
-
Redis默认安装目录在
/usr/local/bin
进入到 /usr/local/bin 目录,有如下Redis文件:
-rwxr-xr-x. 1 root root 4367056 Nov 24 20:27 redis-benchmark -rwxr-xr-x. 1 root root 8153056 Nov 24 20:27 redis-check-aof -rwxr-xr-x. 1 root root 8153056 Nov 24 20:27 redis-check-rdb -rwxr-xr-x. 1 root root 4808288 Nov 24 20:27 redis-cli lrwxrwxrwx. 1 root root 12 Nov 24 20:27 redis-sentinel -> redis-server -rwxr-xr-x. 1 root root 8153056 Nov 24 20:27 redis-server
-
redis-benchmark:性能测试工具,可以在自己本子运行,看看自己本子性能如何
-
redis-check-aof:修复有问题的AOF文件,rdb和aof后面讲
-
redis-check-dump:修复有问题的dump.rdb文件
-
redis-sentinel:Redis集群使用
-
redis-server:Redis服务器启动命令
-
redis-cli:客户端,操作入口
-
-
前台启动(不推荐)
前台启动,命令行窗口关闭后,服务器就停止
./redis-server
-
后台启动
到Redis源码目录,拷贝一份
redis.conf
文件到/etc/redis.conf
[root@localhost redis-5.0.14]# cp redis.conf /etc/redis.conf
修改redis.conf,把daemonize no改成yes
daemonize yes
启动:
./redis-server /etc/redis.conf
-
关闭
单实例关闭:
./redis-cli shutdown
多实例关闭,指定端口关闭:
./redis-cli -p 6379 shutdown
-
客户端访问
[root@localhost bin]# ./redis-cli
如果开启了密码访问,在终端执行命令前需要先验证密码
127.0.0.1:6379> AUTH 123456
-
开启远程访问
1)注释掉 bind (默认情况bind=127.0.0.1只能接受本机的访问请求不写的情况下,无限制接受任何ip地址的访问)
2)设置密码:requirepass 123456(如果开启了protected-mode,那么在没有设定bind ip且没有设密码的情况下,Redis只允许接受本机的响应)
3)重启redis
4)关闭防火墙或者在防火墙中开发redis端口
3.Redis数据类型
Redis是一个Key-Value的存储系统,使用C语言编写。 key的类型是字符串。
value的数据类型有:
- 常用的:string字符串类型、list列表类型、set集合类型、sortedset(zset)有序集合类型、hash类 型。
- 不常见的:bitmap位图类型、geo地理位置类型、stream类型(Redis5.0新增)
3.1 string类型
Redis的String能表达3种值的类型:字符串、整数、浮点数。
常见操作命令如下:
-
set
语法:set <key> <value> [expiration EX seconds \| PX milliseconds] [ NX\| XX]
说明:添加键值对
参数说明:
NX:当数据库中key不存在时,可以将key-value添加数据库
XX:当数据库中key存在时,可以将key-value添加数据库,与NX参数互斥
EX:key的超时秒数
PX:key的超时毫秒数,与EX互斥 -
get
语法:get <key>
说明:查询对应键值 -
**append **
语法:append <key> <value>
说明:将给定的 追加到原值的末尾 -
getset
语法:getset <key> <value>
说明:设置了新值同时获得旧值 -
**setnex **
语法:setnex <key> <value>
说明:只有在 key 不存在时 设置 key 的值 -
get
语法:get <key>
说明:查询对应键值 -
**strlen **
语法:strlen `
说明:获得值的长度 -
incr
语法:incr <key>
说明:递增数字,只能对数字值操作,如果为空,新增值为1 -
incrby
语法:incrby <key> <increment>
说明:将 key 中储存的数字值增加increment
-
decr
语法:decr <key>
说明:将 key 中储存的数字值减去1 -
decrby
语法:decrby <key> <increment>
说明:将 key 中储存的数字值减去increment
-
mset
语法:mset <key1><value1><key2><value2>...
说明:同时设置一个或多个 key-value对 -
mget
语法:mget <key1><key2><key3> .....
说明:同时获取一个或多个 value -
msetnx
语法:msetnx <key1><value1> <key2><value2> .....
说明:同时设置一个或多个,只有在 key 不存在时 设置 key 的值 -
setex
语法:setex <key> <过期时间> <value>
说明:设置键值的同时,设置过期时间,单位秒
应用场景:
-
key和命令是字符串
-
普通的赋值
-
incr用于乐观锁
incr:递增数字,可用于实现乐观锁 watch(事务) -
setnx用于分布式锁
只有在 key 不存在时 设置 key 的值,可用于实现分布式锁
3.2 list类型
list
列表类型可以存储有序、可重复的元素。它的底层实际是个双向链表, 获取头部或尾部附近的记录是极快,通过索引下标的操作中间的节点性能会较差。
list的元素个数最多为2^32-1个(40亿)
常见操作命令如下:
- lpush/rpush
语法:lpush/rpush <key><value1><value2><value3> ....
说明:从左边/右边插入一个或多个值 - lpop/rpop
语法:lpop/rpop <key>
说明:从左边/右边取一个值 - lpushx
语法:lpushx <key><value>
说明:将值插入到列表头部 - rpushx
语法:rpushx <key><value>
说明:将值插入到列表尾部 - lrange
语法:lrange <key><start><stop>
说明:返回列表中指定区间的元素,区间通过start和stop指定 - lindex
语法:lindex<key><index>
说明:获得列表中下标为index的元素 index从0开始 - llen
语法:llen <key>
说明:获得列表中元素个数 - **linsert **
语法:linsert <key> <BEFORE AFTER> <pivot> <value>
说明:将value插入到列表,且位于值pivot之前或之后 - **lrem **
语法:lrem <key> <count> <value>
说明:删除列表中与value相等的元素
当count>0时, lrem会从列表左边开始删除;当count<0时,
lrem会从列表后边开始删除;当count=0时, lrem删除所有值为value的元素 - lset
语法:lset <key> <index> <value>
说明:将列表index位置的元素设置成value的值 - ltrim
语法:ltrim <key><start><stop>
说明:对列表进行修剪,只保留start到stop区间 - rpoplpush
语法:rpoplpush <key1> <key2>
说明:从key1列表右侧取出一个值并插入到key2列表左侧
应用场景:
- 作为栈或队列使用
列表有序可以作为栈和队列使用 - 可用于各种列表,比如用户列表、商品列表、评论列表等。
3.3 set类型
Redis 的 Set 是 String 类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。集合中最大的成员数为 2^32 - 1
常见操作命令如下:
- sadd
语法:sadd <key><value1><value2> .....
说明:将一个或多个 member 元素加入到集合 key 中,已经存在的 member 元素将被忽略 - smembers
语法:smembers <key>
说明:取出该集合的所有值 - sismember
语法:sismember <key><value>
说明:判断集合是否为含有该值,有1,没有0 - scard
语法:scard `
说明:返回该集合的元素个数 - srem
语法:srem <key><value1><value2> ....
说明:删除集合中的一个或多个元素 - spop
语法:spop <key> <count>
说明:随机从该集合中取出count个值,并将该元素删除(count为空,取出一条) - srandmember
语法:srandmember <key> <count>
说明:随机从该集合中取出count个值。不会从集合中删除 (count为空,取出一条) - sinter
语法:sinter <key1> <key2> <key3> ....
说明:求多集合的交集 - sdiff
语法:sdiff <key1> <key2> <key3> ....
说明:求多集合的差集 - sunion
语法:sunion <key1> <key2> <key3> ....
说明:求多集合的并集 - smove
语法:smove <source><destination> <value>
说明:把集合中一个值从一个集合移动到另一个集合
应用场景: 适用于不能重复的且不需要顺序的数据结构 比如:关注的用户,还可以通过spop进行随机抽奖
3.4 sortedset有序集合类型
Redis有序集合与普通集合set非常相似,是一个没有重复元素的字符串集合。
不同之处是有序集合的每个成员都关联了一个**评分(**score),这个评分(score)被用来按照从最低分到最高分的方式排序集合中的成员。集合的成员是唯一的,但是评分可以是重复的 。
因为元素是有序的, 所以你也可以很快的根据评分(score)或者次序(position)来获取一个范围的元素。
访问有序集合的中间元素也是非常快的,因此你能够使用有序集合作为一个没有重复成员的智能列表。
常见操作命令如下:
- zadd
语法:zadd <key><score1><value1><score2><value2>…
说明:将一个或多个 member 元素及其 score 值加入到有序集 key 当中 - zrange
语法:zrange <key><start><stop>
说明:返回有序集 key 中,下标在start 和stop之间的元素,按分数递增 排序 - zrevrange
语法:zrevrange <key><start><stop>
说明:返回有序集 key 中,下标在start 和stop之间的元素,按分数递减 排序 - zcard
语法:zcard `
说明:返回该集合的元素个数 - zrem
语法:zrem <key> <member> <member> ....
说明:删除集合中的一个或多个元素 - zcount
语法:zcount <key> <min> <max>
说明:返回集合中score值在[min,max]区间 的元素数量 - zscore
语法:zscore <key> <member>
说明:获得集合中member的分值 - zrank
语法:zrank <key> <member>
说明:获得集合中member的排名(按分值从 小到大) - zrevrank
语法:zrevrank <key> <member>
说明:获得集合中member的排名(按分值从 大到小) - ZINCRBY
语法:ZINCRBY <key> <increment> <member>
说明:在集合的member分值上加increment
应用场景: 由于可以按照分值排序,所以适用于各种排行榜。比如:点击排行榜、销量排行榜、关注排行榜等。
3.5 hash类型
Redis hash 是一个键值对集合。Redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象,类似Java里面的Map<String,Object>
常见操作命令如下:
- hset
语法:hset <key> <field> <value>
说明:赋值,不区别新增或修改 - hmset
语法:hmset <key1><field1><value1><field2><value2>...
说明:批量赋值 - hexists
语法:hexists <key1> <field>
说明:查看某个field是否存在 - hget
语法:hget <key1><field>
说明:获取一个字段值 - hmget
语法:hmget <key1> <field1> <field2>....
说明:获取多个字段值 - hgetall
语法:hgetall <key>
说明:查看所有的key value - **zrevrank **
语法:zrevrank <key> <member>
说明:获得集合中member的排名(按分值从 大到小) - hdel
语法:hdel <key1> <field1> <field2>....
说明:删除指定的字段 - hincrby
语法:hincrby <key><field><increment>
说明:为哈希表 key 中的 field 的值加上increment - hsetnx
语法:hsetnx <key><field><value>
说明:将哈希表 key 中的域 field 的值设置为 value ,当且仅当域 field 不存在
应用场景: 对象的存储 ,表数据的映射
3.6 bitmap类型
bitmap是进行位操作的, 通过一个bit位来表示某个元素对应的值或者状态,其中的key就是对应元素本身。 bitmap本身会极大的节省储存空间。
常见操作命令如下:
- setbit
语法:setbit <key> <offset> <value>
说明:给一个指定key的值得第offset位 赋值为value(value只能是0或者 1)。 - getbit
语法:getbit <key> <offset>
说明:获得key在offset处的bit值 - bitcount
语法:bitcount <key>
说明:获得key的bit位为1的个数 - bitpos
语法:bitpos <key> <value>
说明:返回第一个被设置为bit值的索引值 - bitop
语法:bitop and[or/xor/not] <destkey> <key> …
说明:对多个key 进行逻辑运算后存入destkey 中
应用场景:
- 用户每月签到,用户id为key , 日期作为偏移量 1表示签到
- 统计活跃用户, 日期为key,用户id为偏移量 1表示活跃
- 查询用户在线状态, 日期为key,用户id为偏移量 1表示在线
用法示例
127.0.0.1:6379> setbit user:1000 20211112 1 #id为1000的用户20211112签到
(integer) 0
127.0.0.1:6379> setbit user:1000 20211113 1 #id为1000的用户20211113签到
(integer) 0
127.0.0.1:6379> getbit user:1000 20211112 #获得id为1000的用户20211112签到状态,1表示签到
(integer) 1
127.0.0.1:6379> getbit user:1000 20211113 #获得id为1000的用户20211113签到状态 1表示未签到
(integer) 0
127.0.0.1:6379> bitcount user:1000 # 获得id为1000的用户签到次数
(integer) 2
127.0.0.1:6379> bitpos user:1000 1 #id为1000的用户第一次签到的日期
(integer) 20211112
127.0.0.1:6379> setbit 20211112 1000 1 #2021-11-12的1000号用户上线
(integer) 0
127.0.0.1:6379> setbit 20211113 1001 1 #2021-11-13的1001号用户上线
(integer) 0
127.0.0.1:6379> setbit 20211114 1002 1 #2021-11-14的1002号用户上线
(integer) 0
127.0.0.1:6379> bitcount 20211112 #2021-11-12的上线用户有1个
(integer) 1
127.0.0.1:6379> bitop or desk1 20211112 20211114 #合并2021-11-12的用户和2021-11-14上线了的用户
(integer) 126
127.0.0.1:6379> bitcount desk1 #统计2021-11-12和2021-11-14都上线的用户个数
(integer) 3
3.7 geo地理位置类型
geo是Redis用来处理位置信息的。主要是利用了Z阶曲线、Base32编码和 geohash算法。
-
Z阶曲线
在x轴和y轴上将十进制数转化为二进制数,采用x轴和y轴对应的二进制数依次交叉后得到一个六位数编 码。把数字从小到大依次连起来的曲线称为Z阶曲线,Z阶曲线是把多维转换成一维的一种方法。
-
Base32编码
Base32这种数据编码机制,主要用来把二进制数据编码成可见的字符串,其编码规则是:任意给定一 个二进制数据,以5个位(bit)为一组进行切分(base64以6个位(bit)为一组),对切分而成的每个组进行编 码得到1个可见字符。Base32编码表字符集中的字符总数为32个(0-9、b-z去掉a、i、l、o),这也是 Base32名字的由来。
-
geohash算法
Gustavo在2008年2月上线了geohash.org网站。Geohash是一种地理位置信息编码方法。 经过 geohash映射后,地球上任意位置的经纬度坐标可以表示成一个较短的字符串。可以方便的存储在数据 库中,附在邮件上,以及方便的使用在其他服务中。以北京的坐标举例,[39.928167,116.389550]可以 转换成 wx4g0s8q3jf9 。
Redis中经纬度使用52位的整数进行编码,放进zset中,zset的value元素是key,score是GeoHash的 52位整数值。在使用Redis进行Geo查询时,其内部对应的操作其实只是zset(skiplist)的操作。通过zset 的score进行排序就可以得到坐标附近的其它元素,通过将score还原成坐标值就可以得到元素的原始坐 标。
常见操作命令如下:
- geoadd
语法:geoadd <key> <longitude> <latitude> <member> [longitude latitude member ...]
说明:添加地理坐标 - geohash
语法:geohash <key> <member> [member ...]
说明:返回标准的 geohash串 - geopos
语法:geopos <key> <member>...
说明:返回成员经纬度 - geopos
语法:geopos <key> <member1> <member2> [unit]
说明:计算成员间距离 - georadiusbymember
语法:georadiusbymember key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [ST]
说明:根据成员查找附 近的成员
应用场景:
- 记录地理位置
- 计算距离
- 查找"附近的人"
应用示例
127.0.0.1:6379> geoadd user:address 116.435889 39.918255 xiaoming 116.420366 39.881501 lisi #添加xiaoming和lisi的geohash码的用户地址
(integer) 2
127.0.0.1:6379> geohash user:address xiaoming lisi #获取xiaoming和lisi的geohash码
1) "wx4g1dfh8y0"
2) "wx4fchnwx40"
127.0.0.1:6379> geopos user:address xiaoming # 获取xiaoming的经纬度信息
1) 1) "116.4358869194984436"
2) "39.91825515346047837"
127.0.0.1:6379> geodist user:address xiaoming lisi #获取xiaoming和lisi之间的距离,单位:米
"4297.0882"
127.0.0.1:6379> geodist user:address xiaoming lisi km #获取xiaoming和lisi之间的距离,单位:千米
"4.2971"
#获取距离lisi 10KM以内的3名用户,按照距离从近到远排序。参数 withcoord:显示经纬度 withdist:显示距离 count:显示的成员数量
127.0.0.1:6379> georadiusbymember user:address lisi 10 km withcoord withdist count 3 asc
1) 1) "lisi"
2) "0.0000"
3) 1) "116.42036765813827515"
2) "39.88150169665006928"
2) 1) "xiaoming"
2) "4.2971"
3) 1) "116.4358869194984436"
2) "39.91825515346047837"
127.0.0.1:6379>
3.8 stream类型
stream是Redis5.0后新增的数据结构,用于可持久化的消息队列。
几乎满足了消息队列具备的全部内容,包括:
- 消息ID的序列化生成
- 消息遍历
- 消息的阻塞和非阻塞读取
- 消息的分组消费
- 未完成消息的处理
- 消息队列监控
比较少用,相比RabbitMQ、kafka等消息队列没有看出有什么优势。
PS:搞不懂为什么会出这个stream类型
详细可以参考官方教程:https://redis.io/topics/streams-intro