基础
诞生于2009年,全称Remote Dictionary Server
,远程词典服务器,是一个基于内存的键值型NoSQL
数据库。
特征:
- 键值型,
value
支持多种不同数据结构,功能丰富 - 单线程,每个命令具备原子性
- 低延迟,速度快(基于内存、
IO
多路复用、良好的编码) - 支持数据持久化
- 支持主从集群、分片集群
- 支持多语言客户端
安装依赖
Redis
是基于c语言编写的,因此要安装gcc
依赖
yum install -y gcc tcl
Linux
环境:
- 将安装包放在
/usr/local/src
目录 - 进入该目录,解压该文件
tar -zxvf redis-6.2.6.tar.gz
- 进入该文件夹,安装
默认安装到
cd redis-6.2.6
make && make installusr/local/bin
目录下
启动方式
直接启动
- 在该文件夹下运行redis
redis-server
后台启动
修改相应的配置文件,然后启动
在该文件夹下
- 备份配置文件
cp redis.conf redis.conf.bck
- 修改redis.conf文件中的一些配置:
# 允许访问的地址,默认是127.0.0.1,会导致只能在本地访问。修改为0.0.0.0则可以在任意IP访问,生产环境不要设置为0.0.0.0
bind 0.0.0.0
# 守护进程,修改为yes后即可后台运行
daemonize yes
# 密码,设置后访问Redis必须输入密码
requirepass 123321
# / 搜索功能,n键下一个搜到的 对象 - Redis的其它常见配置:
# 监听的端口
port 6379
# 工作目录,默认是当前目录,也就是运行redis-server时的命令,日志、持久化等文件会保存在这个目录
dir .
# 数据库数量,设置为1,代表只使用1个库,默认有16个库,编号0~15
databases 1
# 设置redis能够使用的最大内存
maxmemory 512mb
# 日志文件,默认为空,不记录日志,可以指定日志文件名
logfile "redis.log" - 启动Redis:
# 进入redis安装目录
cd /usr/local/src/redis-6.2.6
# 启动
redis-server redis.conf
# 查看状态
ps -ef | grep redis - 停止服务:
# 利用redis-cli来执行 shutdown 命令,即可停止 Redis 服务,
# 因为之前配置了密码,因此需要通过 -u 来指定密码
redis-cli -u 123321 shutdown
# 杀死进程
kill -9 进程ID
开机自启
我们也可以通过配置来实现开机自启。
-
首先,新建一个系统服务文件:
vi /etc/systemd/system/redis.service
内容如下:
[Unit]
Description=redis-server
After=network.target
[Service]
Type=forking
ExecStart=/usr/local/bin/redis-server /usr/local/src/redis-6.2.6/redis.conf
PrivateTmp=true
[Install]
WantedBy=multi-user.target -
然后重载系统服务:
systemctl daemon-reload
-
可以用下面这组命令来操作redis:
# 启动
systemctl start redis
# 停止
systemctl stop redis
# 重启
systemctl restart redis
# 查看状态
systemctl status redis -
执行下面的命令,可以让
redis
开机自启:systemctl enable redis
Redis桌面客户端
安装完成Redis
,我们就可以操作Redis
,实现数据的CRUD
了。这 需要用到Redis
客户端,包括:
- 命令行客户端
- 图形化桌面客户端
- 编程客户端
Redis命令行客户端
Redis
安装完成后就自带了命令行客户端:redis-cli
,使用方式如下:
redis-cli [options] [commonds]
其中常见的options
有:
-h 127.0.0.1
:指定要连接的redis
节点的IP
地址,默认是127.0.0.1
-p 6379
:指定要连接的redis
节点的端口,默认是6379
-a 123321
:指定redis
的访问密码
其中的commonds
就是Redis
的操作命令,例如:
ping
:与redis
服务端做心跳测试,服务端正常会返回pong
不指定commond
时,会进入redis-cli
的交互控制台:
# 没有用户名就只填密码
控制台> AUTH [用户名] [密码]
图形化桌面客户端
GitHub
上有编写了Redis
的图形化桌面客户端,地址:https://github.com/uglide/RedisDesktopManager
不过该仓库提供 的是RedisDesktopManager
的源码,并未提供windows
安装包。
在下面这个仓库可以找到安装包:https://github.com/lework/RedisDesktopManager-Windows/releases
如果图形化工具无法连接,可能是防火墙的问题
# 关闭防火墙命令
systemctl stop firewalld.service
或开放6379
端口:
-
检查防火墙状态:
sudo systemctl status firewalld
-
开启 6379 端口:
sudo firewall-cmd --permanent --add-port=6379/tcp
-
重新加载防火墙:
sudo firewall-cmd --reload
-
确认端口已开启:
sudo firewall-cmd --list-ports
这样就可以开启 6379
端口来允许 Redis
连接。如果你使用的是 iptables
而不是 firewalld
,命令会有所不同。
Redis
默认有16个仓库,编号从0至15. 通过配置文件可以设置仓库数量,但是不超过16,并且不能自定义仓库名称。
如果是基于redis-cli
连接Redis
服务,可以通过select
命令来选择数据库:
# 选择 0号库
select 0
数据结构
是一个key-value
的数据库,key
一般是Stirng
类型,value
的类型很多
key | value |
---|---|
String | hello world |
Hash | {name: "jack"} |
List | [A -> B -> C -> C] |
Set | {A, B, C} |
SortedSet | {A: 1, B: 2} |
GEO | {A: (123.3, 33) } |
BitMap | 0110110101110101011 |
HyperLog | 0110110101110101011 |
Redis
为了方便我们学习,将操作不同数据类型的命令也做了分组,在官网可以查看到不同的命令
不同类型的命令称为一个group
,我们也可以通过help
命令来查看各种不同group
的命令
# 查看对应组的帮助
help [@group]
Redis通用命令
通用指令是部分数据类型的,都可以使用的指令,常见的有:
KEYS
:查看符合模板的所有key
DEL
:删除一个指定的key
EXISTS
:判断key
是否存在EXPIRE
:给一个key
设置有效期,有效期到期时该key
会被自动删除TTL
:查看一个KEY
的剩余有效期- -1为永久有效,-2为过期
通过 help [command]
可以查看一个命令的具体用法,例如:
# 查看keys命令的帮助信息:
127.0.0.1:6379> help keys
KEYS pattern
summary: Find all keys matching the given pattern
since: 1.0.0
group: generic
String类型
String
类型,也就是字符串类型,是Redis
中最简单的存储类型。
其value
是字符串,不过根据字符串的格式不同,又可以分为3类:
string
:普通字符串int
:整数类型,可以做自增、自减操 作float
:浮点类型,可以做自增、自减操作
不管是哪种格式,底层都是字节数组形式存储,只不过是编码方式不同。字符串类型的最大空间不能超过512m.
String的常见命令
String的常见命令有:
SET
:添加或者修改已经存在的一个String
类型的键值对GET
:根据key获取String
类型的value
MSET
:批量添加多个String
类型的键值对MGET
:根据多个key获取多个String
类型的value
INCR
:让一个整型的key
自增1INCRBY
:让一个整型的key
自增并指定步长,例如:incrby num 2
让num
值自增2INCRBYFLOAT
:让一个浮点类型的数字自增并指定步长SETNX
:添加一个String
类型的键值对,前提是这个key
不存在,否则不执行SETEX
:添加一个String
类型的键值对,并且指定有效期
Key结构
Redis
没有类似MySQL
中的Table
的概念,可以通过给key
添加前缀加以区分不同类型的key
,不过这个前缀不是随便加的,有一定的规范:
Redis
的key
允许有多个单词形成层级结构,多个单词之间用 :
隔开,格式如下:
项目名:业务名:类型:id
这个格式并非固定。
如果Value
是一个Java
对象,例如一个User
对象,则可以将对象序列化为JSON
字符串后存储:
KEY | VALUE |
---|---|
heima:user:1 | {"id":1, "name": "Jack", "age": 21} |
heima:product:1 | {"id":1, "name": "小米11", "price": 4999} |
并且,在Redis
的桌面客户端中,会以相同前缀作为层级结构,让数据看起来层次分明,关系清晰
Hash类型
Hash
类型,也叫散列,其value
是一个无序字典,类似于Java
中的HashMap
结构。
String
结构是将对象序列化为JSON
字符串后存储,当需要修改对象某个字段时很不方便:
Hash
结构可以将对象中的每个字段独立存储,可以针对单个字段做CRUD
:
Hash
的常见命令有:
-
HSET key field value
:添加或者修改hash
类型key
的field
的值 -
HGET key field
:获取一个hash
类型key
的field
的值 -
HMSET
:批量添加多个hash
类型key
的field
的值 -
HMGET
:批量获取多个hash
类型key
的field
的值 -
HGETALL
:获取一个hash
类型的key
中的所有的field
和value
-
HKEYS
:获取一个hash
类型的key
中的所有的field
-
HINCRBY
:让一个hash
类型key
的字段值自增并指定步长 -
HSETNX
:添加一个hash
类型的key
的field
值,前提是这个field
不存在,否则不执行
List类型
List
类型与Java
中的LinkedList
类似,可以看做是一个双向链表结构。既可以支持 正向检索和也可以支持反向检索。
特征也与LinkedList
类似:
- 有序
- 元素可以重复
- 插入和删除快
- 查询速度一般
常用来存储一个有序数据,例如:朋友圈点赞列表,评论列表等。
List
的常见命令有:
LPUSH key element ...
:向列表左侧插入一个或多个元素LPOP key
:移除并返回列表左侧的第一个元素,没有则返回nil
RPUSH key element ...
:向列表右侧插入一个或多个元素RPOP key
:移除并返回列表右侧的第一个元素LRANGE key star end
:返回一段角标范围内的所有元素BLPOP
和BRPOP
:与LPOP
和RPOP
类似,只不过在没有元素时等待指定时间(单位是秒),而不是直接返回nil
Set类型
Redis
的Set
结构与Java
中的HashSet
类似,可以看做是一个value
为null
的HashMap
。因为也是一个hash
表,因此具备与HashSet
类似的特征:
-
无序
-
元素不可重复
-
查找快
-
支持交集、并集、差集等功能
Set
的常见命令有:
SADD key member ...
:向set
中添加一个或多个元素SREM key member ...
: 移除set中的指定元素SCARD key
: 返回set中元素的个数SISMEMBER key member
:判断一个元素是否存在于set中SMEMBERS
:获取set中的所有元素SINTER key1 key2 ...
:求key1与key2的交集SDIFF key1 key2
: 求key1与key2的不同SUNION key1 key2
: 求key1与key2的并集
SortedSet类型
Redis
的SortedSet
是一个可排序的set集合,与Java
中的TreeSet有些类似,但底层数据结构却差别很大。SortedSet
中的每一个元素都带有一个score
属性,可以基于score
属性对元素排序,底层的实现是一个跳表(SkipList
)加 hash
表。
SortedSet
具备下列特性:
- 可排序
- 元素不重复
- 查询速度快
因为SortedSet的可排序特性,经常被用来实现排行榜这样的功能。
SortedSet的常见命令有:
ZADD key score member
:添加一个或多个元素到sorted set
,如果已经存在则更新其score
值ZREM key member
:删除sorted set
中的一个指定元素ZSCORE key member
: 获取sorted set
中的指定元素的score
值ZRANK key member
:获取sorted set
中的指定元素的排名ZCARD key
:获取sorted set
中的元素个数ZCOUNT key min max
:统计score
值在给定范围内的所有元素的个数ZINCRBY key increment member
:让sorted set
中的指定元素自增,步长为指定的increment
值ZRANGE key min max
:按照score
排序后,获取指定排名范围内的元素ZRANGEBYSCORE key min max
:按照score
排序后,获取指定score
范围内的元素ZDIFF
、ZINTER
、ZUNION
:求差集、交集、并集
注意:所有的排名默认都是升序,如果要降序则在命令的Z
后面添加REV
即可,例如:
-
升序获取
sorted set
中的指定元素的排名:ZRANK key member
-
降序获取
sorted set
中的指定元素的排名:ZREVRANK key memeber
GEO数据结构
是Geolocation
的简写,代表地理坐标。Redis中允许存储地理坐标信息,帮助我们根据经纬度来检索数据
常见命令:
GEOADD
:添加一个地理空间信息,包含:经度,维度,值GEODIST
:计算指定的连个点之间的距离并返回GEOHASH
:将指定member
的坐标转为hash
字符串形式并返回GEOPOS
:返回指定member
的坐标GEORADIUS
:指定圆心、半径,找到该圆内包含的所有member
,并按照与圆心之间的距离排序后返回(6.2以后废弃)GEOSEARCH
:在指定范围内搜索member
,并按照与指定点之间的距离排序后返回(6.2新功能)GEOSEARCHSTORE
:与GEOSEARCH
功能一致,可以把结果储存到一个指定的key
(6.2新功能)
BitMap
Redis
中是利用string
类型数据结构实现BitMap
,因此最大上限是512M,转换为bit
则是 2^32个bit
位。
操作命令有:
SETBIT
:向指定位置(offset
)存入一个0或1GETBIT
:获取指定位置(offset
)的bit
值BITCOUNT
:统计BitMap
中值为1的bit位的数量BITFIELD
:操作(查询、修改、自增)BitMap
中bit
数组中的指定位置(offset
)的值BITFIELD_RO
:获取BitMap
中bit
数组,并以十进制形式返回BITOP
:将多个BitMap
的结果做位运算(与 、或、异或)BITPOS
:查找bit
数组中指定范围内第一个0或1出现的位置
HyperLogLog
UV统计
首先我们搞懂两个概念:
UV
:全称Unique Visitor
,也叫独立访客量,是指通过互联网访问、浏览这个网页的自然人。1天内同一个用户多次访问该网站,只记录1次。PV
:全称Page View
,也叫页 面访问量或点击量,用户每访问网站的一个页面,记录1次PV
,用户多次打开页面,则记录多次PV
。往往用来衡量网站的流量。
通常来说UV
会比PV
大很多,所以衡量同一个网站的访问量,我们需要综合考虑很多因素,所以我们只是单纯的把这两个值作为一个参考值
UV
统计在服务端做会比较麻烦,因为要判断该用户是否已经统计过了,需要将统计过的用户信息保存。但是如果每个访问的用户都保存到Redis
中,数据量会非常恐怖,那怎么处理呢?
Hyperloglog(HLL)
是从Loglog
算法派生的概率算法,用于确定非常大的集合的基数,而不需要存储其所有值。相关算法原理大家可以参考:https://juejin.cn/post/6844903785744056333#heading-0
Redis
中的HLL
是基于string
结构实现的,单个HLL
的内存永远小于16kb,内存占用低!作为代价,其测量结果是概率性的,有小于0.81%的误差。不过对于UV
统计来说,这完全可以忽略。
操作:
PFADD key element [element...]
PFOUNT key [key...]
PFMERGE destkey sourcekey [sourcekey...]