Redis 安装 & 自启动
1、下载redis
代码语言:javascript复制https://download.redis.io/releases/
wget https://download.redis.io/releases/redis-6.2.1.tar.gz
2、redis 安装包拷贝到/opt/ 目录
代码语言:javascript复制mv redis-6.2.1.tar.gz /opt
3、解压
代码语言:javascript复制tar -zvxf redis-6.2.1.tar.gz
4、安装gcc
代码语言:javascript复制yum install gcc
5、进入目录
代码语言:javascript复制cd redis-6.2.1
6、编译
代码语言:javascript复制make
7、安装
代码语言:javascript复制make PREFIX=/usr/local/redis install
ln -s /usr/local/redis/bin/redis-cli /usr/local/bin/redis-cli
ln -s /usr/local/redis/bin/redis-server /usr/local/bin/redis-server
安装目录:/usr/local/redis
# redis-benchmark:性能测试工具
# redis-check-aof:修复有问题的AOF文件
# redis-check-dump:修复有问题的dump.rdb文件
# redis-sentinel:redis集群使用
# redis-server:redis服务器启动命令
# redis-cli:客户端操作入口
rm -rf /opt/redis-6.2.1.tar.gz
8、启动redis(后端启动)
代码语言:text复制mkdir /etc/redis/
# 复制redis.conf文件到/etc/redis/目录
cp /opt/redis-6.2.1/redis.conf /etc/redis/redis.conf
rm -rf /opt/redis-6.2.1
# 后台启动设置daemonize改为yes
daemonize yes
# 后台启动设置密码
requirepass 123456
# 后台启动监听所有地址
bind 0.0.0.0
# 后台启动监听端口
port 6380
# 启动redis
redis-server /etc/redis/redis.conf
9、关闭redis
代码语言:javascript复制redis-cli -h 127.0.0.1 -p 6380 --askpass shutdown
10、redis命令窗口
代码语言:javascript复制redis-cli -h 127.0.0.1 -p 6380 --askpass
11、自启动redis
代码语言:javascript复制vi /etc/systemd/system/redis.service
代码语言:javascript复制[Unit]
Description=redis-server
After=network.target
[Service]
Type=forking
ExecStart=/usr/local/redis/bin/redis-server /etc/redis/redis.conf
PrivateTmp=true
[Install]
WantedBy=multi-user.target
代码语言:javascript复制# 重新加载服务
systemctl daemon-reload
# 启动redis
systemctl start redis
# 查看redis状态
systemctl status redis
# 重启redis
systemctl restart redis
# 停止redis
systemctl stop redis
# 开机自启动redis
systemctl enable redis
# 关闭开机自启动
systemctl disable redis
12、redis 功能
代码语言:javascript复制一、默认端口6379
二、默认16个数据库
四、统一密码管理,所有的库密码相同
五、单线程 多路复用
六、支持多数据类型
七、支持持久化
13、多路复用
代码语言:javascript复制使用一个线程来检测多个文件描述符(socket)的就绪状态。
比如调用select函数传入多个文件描述符,如果有一个文件描述符就绪,则返回,否则阻塞到超时。
得到就绪状态后进行真正的操作可以在同一个线程里执行,也可以启动线程执行。
14、单线程
代码语言:javascript复制redis6.0中提供了多线程,命令解析和io数据读写部分采用了多线程,而命令的执行还是采用的是单线程。
多个客户端发送来的命令会在同一个线程去执行,相当于排队执行,效率极高。
Redis 数据类型
Redis 命令参考文档
代码语言:javascript复制http://doc.redisfans.com/
数据类型是value的数据类型,key的类型都是字符串。
redis键(key)
代码语言:javascript复制keys *:查看当前库所有的key
代码语言:javascript复制exists key:判断某个key是否存在
代码语言:javascript复制type key:查看你的key是什么类型
代码语言:javascript复制del key:删除指定的key数据
代码语言:javascript复制expire key 10:为指定的key设置有效期10秒
代码语言:javascript复制ttl key:查看指定的key还有多少秒过期,-1:表示永不过期,-2:表示已过期
代码语言:javascript复制select dbindex:切换数据库【0-15】,默认为0
代码语言:javascript复制dbsize:查看当前数据库key的数量
代码语言:javascript复制flushdb:清空当前库
代码语言:javascript复制flushall:清空全部库
redis字符串(String)
String类型是Redis最基本的数据类型,一个Redis中字符串value最多可以是512M。String的数据结构为简单动态字符串,采用分配冗余空间的方式来减少内存的频繁分配。
代码语言:javascript复制set:添加键值对
set key value
set key value [EX seconds|PX milliseconds|EXAT timestamp|PXAT milliseconds-timestamp|KEEPTTL] [NX|XX]
NX:当数据库中key不存在时,可以将key-value添加到数据库
XX:当数据库中key存在时,可以将key-value添加数据库,与NX参数互斥
EX:key的超时秒数
PX:key的超时毫秒数,与EX互斥
value:若包含空格、特殊字符,需用双引号包裹
SET key-with-expire-time "hello" EX 10086
代码语言:javascript复制get:获取值
get <key>
get name
代码语言:javascript复制apend:追价值
append <key> <value> # 返回value长度
append name hello
代码语言:javascript复制strlen:获取值的长度
strlen <key>
strlen name
代码语言:javascript复制setnx:key不存在时,设置key的值
setnx <key> <value>
setnx name full # 存在设置失败返回0
setnx fullname ready # 不存在设置成功返回1
代码语言:javascript复制incr:原子递增1
incr <key>
set age 30 #age值为30
incr age #返回31
代码语言:javascript复制decr:原子递减1
decr <key>
decr age # 返回30
代码语言:javascript复制incrby/decrby:递增或者递减指定的数字
incrby/decrby <key> <步长>
代码语言:javascript复制mset:同时设置多个key-value
mset <key1> <value1> <key2> <value2>
代码语言:javascript复制mget:获取多个key对应的值
mget <key1> <key2>
代码语言:javascript复制msetnx:当多个key都不存在时,则设置成功
msetnx <key1> <value1> <key2> <value2>
代码语言:javascript复制getrange:获取值的范围
getrange key start end
代码语言:javascript复制setrange:覆盖指定位置的值
setrange <key> <起始位置> <value>
代码语言:javascript复制setex:设置键值&过期时间(秒)
setex <key> <过期时间(秒)> <value>
代码语言:javascript复制getset:以新换旧,设置新值同时返回旧值
getset <key> <value>
redis列表(List)
redis列表 单键多值,是简单的字符串列表,按照插入顺序排序。底层实际上是使用双向链表实现的,对两端的操作性能很高,通过索引下标操作中间节点性能会较差。List的数据结构为快速链表quickList。在列表元素较少的情况下会使用一块连续的内存存储,这个结构是ziplist。它将所有的元素紧挨着一起存储,分配的是一块连续的内存。当就比较多的时候才会改成quickList,将多个ziplist使用双向指针串起来使用。
代码语言:javascript复制lpush/rpush:从左边或者右边插入一个或多个值
lpush/rpush <key1> <value1> <key2> <value2>
代码语言:javascript复制lrange:从列表左边获取指定范围内的值
lrange <key> <star> <stop>
lrange course 0 -1 #取出course集合中所有元素
代码语言:javascript复制lpop/rpop:从左边或者右边弹出多个元素
lpop/rpop <key> <count>
代码语言:javascript复制rpoplpush:从一个列表右边弹出一个元素放到另外一个列表中
rpoplpush source destination
代码语言:javascript复制lindex:获取指定索引位置的元素(从左到右)
lindex key index
代码语言:javascript复制llen:获得列表长度
llen key
代码语言:javascript复制linsert:在某个值的前或者后面插入一个值
linsert <key> before|after <value> <newvalue>
linsert name before tom lily #tom前面添加lily
代码语言:javascript复制lrem:删除指定数量的某个元素
LREM key count value
代码语言:javascript复制lset:替换指定位置的值
lset <key> <index> <value>
redis集合(Set)
set是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择。set是string类型的无序集合,他的底层实际是一个value为null的hash表,收益添加,删除,查找复杂度都是O(1)。随着数据的增加,查找数据的时间不变。set数据结构是字典,字典是用hash表实现的。
代码语言:javascript复制sadd:添加一个或多个元素
sadd <key> <value1> <value2>
代码语言:javascript复制sismember:判断集合中是否有某个值
sismember <key> <value>
代码语言:javascript复制scard:返回集合中元素的个数
scard <key>
代码语言:javascript复制srem:删除多个元素
srem key member [member ...]
代码语言:javascript复制smembers:取出所有元素
smembers <key>
代码语言:javascript复制spop:随机弹出多个值
spop <key> <count>
代码语言:javascript复制srandmember:随机获取多个元素,不会从集合中删除
srandmember <key> <count>
代码语言:javascript复制smove:将某个原创从一个集合移动到另一个集合
smove <source> <destination> member
代码语言:javascript复制sinter:取多个集合的交集
sinter key [key ...]
代码语言:javascript复制sinterstore:将多个集合的交集放到一个新的集合中
sinterstore destination key [key ...]
代码语言:javascript复制sunion:取多个集合的并集,自动去重
sunion key [key ...]
代码语言:javascript复制sunionstore:将多个集合的并集放到一个新的集合中
sinterstore destination key [key ...]
代码语言:javascript复制sdiff:取多个集合的差集
SDIFF key [key ...]
代码语言:javascript复制sdiffstore:将多个集合的差集放到一个新的集合中
sdiffstore destination key [key ...]
redis哈希(Hash)
Redis hash是一个键值对集合。hash特别适合用于存储对象。Map<String,Object>Hash类型对应的数据结构:ziplist(压缩列表),hashtable(哈希表)。当field-value长度较短个数较少时,使用ziplist,否则使用hashtable。
代码语言:javascript复制hset:设置多个field的值
hset key field value [field value ...]
代码语言:javascript复制hget:获取指定filed的值
hget key field
代码语言:javascript复制hgetall:返回hash表所有的域和值
hgetall key
代码语言:javascript复制hexists:判断给定的field是否存在 1:存在,0:不存在
hexists key field
代码语言:javascript复制hkeys:列出所有的filed
hkeys key
代码语言:javascript复制hvals:列出所有的value
hvals key
代码语言:javascript复制hlen:返回filed的数量
HLEN key
代码语言:javascript复制hincrby:filed的值加上指定的增量
hincrby key field increment
hincrby siteInfo pv 10
代码语言:javascript复制hsetnx:当filed不存在的时候,设置filed的值
hsetnx key field value
redis有序集合(Zset)
有序集合的每个成员(member)都关联了一个评分(score),这个评分(score)被用来按照从最低分到最高分的方式排序集合中的成员。集合的成员(member)是唯一的,但是评分是可以重复的。元素是有序的,所以你可以很快的根据评分(score)来获取一个范围的元素。访问有序集合中的中间元素也是非常快的,能够使用有序集合作为一个没有重复成员(member)的智能列表。SortedSet(zset)是redis提供的一个非常特别的数据结构,内部使用到了2种数据结构:hash表快速定位元素定义的score,时间复杂度为O(1)和跳表(skiplist)实现简单,插入、删除、查找的复杂度均为O(logN)
代码语言:javascript复制zadd:添加元素
zadd <key> <score1> <member1> <score2> <member2> ...
zadd topn 100 java 80 c 90 c 50 php 70 js
代码语言:javascript复制zrange:score升序,获取指定索引范围的元素
zrange key start top [withscores]
zrange topn 0 -1 # 按score升序,返回topn中所有元素的值
代码语言:javascript复制zrevrange:score降序,获取指定索引范围的元素
zrevrange key start stop [WITHSCORES]
代码语言:javascript复制zrangebyscore:按照score升序,返回指定score范围内的数据
zrangebyscore key min max [WITHSCORES] [LIMIT offset count]
zrangebyscore topn 70 90 #score升序,获取score位于[70,90]区间中的元素值
代码语言:javascript复制zrevrangebyscore:按照score降序,返回指定score范围内的数据
zrevrangebyscore key max min [WITHSCORES] [LIMIT offset count]
zrevrangebyscore topn 100 90 #score降序,获取score位于[70,90]区间中的元素值
代码语言:javascript复制zincrby:为指定元素的score加上指定的增量
zincrby key increment member
zincrby topn 5 java
代码语言:javascript复制zrem:删除集合中多个元素
zrem key member [member ...]
zrem topn c c #删除集合topn中的2个元素:c、c
代码语言:javascript复制zremrangebyrank:根据索引范围删除元素
zremrangebyrank key start stop
代码语言:javascript复制zremrangebyscore:根据score的范围删除元素
zremrangebyscore key min max
代码语言:javascript复制zcount:统计指定score范围内元素的个数
zcount key min max
代码语言:javascript复制zrank:按照score升序,返回某个元素在集合中的排名
zrank key member # 有序集成员按值递增(从小到大)顺序
代码语言:javascript复制zrevrank:按照score降序,返回某个元素在集合中的排名
zrevrank key member 有序集成员按值递减(从大到小)排序
代码语言:javascript复制zscore:返回集合中指定元素的score
zscore key member
redis 位操作字符串(Bitmaps)
合理地使用位操作能够有效地提高内存使用率和开发效率。Bitmaps本身不是一种数据类型, 实际上它就是字符串(key-value) , 但是它可以对字符串的位进行操作,字符串中每个字符对应1个字节,也就是8位,一个字符可以存储8个bit位信息。
代码语言:javascript复制setbit:设置某个偏移量的值(0或1)
SETBIT key offset value
setbit bit 10086 1
应用场景:
每个独立用户是否访问过网站存放在bitmaps中,将访问的用户记做1,没有访问的用户记做0,用户id作为offset
假设现在有20个用户,userid=1,6,11,15,19的用户对网站进行了访问,那么userid=1,6,11,15,19的用户value是1
其他用户是0
users:20220409 这个bitmaps中表示2022-04-09这天独立访问的用户,如下
setbit users:20220409 1 1
setbit users:20220409 6 1
setbit users:20220409 11 1
setbit users:20220409 15 1
setbit users:20220409 19 1
代码语言:javascript复制getbit:获取某个偏移位的值
GETBIT key offset
应用场景:
获取当前用户是否在2022-04-09这天访问过网站,如下 访问过的值是1,没有访问过的值是0
getbit users:20220409 15
代码语言:javascript复制bitcount:统计bit位都为1的数量
BITCOUNT key [start] [end]
应用场景:
获取在2022-04-09这天访问过网站用户量
bitcount users:20220409
代码语言:javascript复制bittop:对一个多个bitmaps执行位操作
BITOP operation destkey key [key ...]
应用场景:假设网站有 1 亿用户, 每天独立访问的用户有 5 千万, 如果每天用集合类型和 Bitmaps 分别存储活跃用户。
代码语言:javascript复制数据类型:set集合
每个用户 id 占用空间:64 位
需要存储的用户量:50000000
全部内存量:64 位 * 50000000 = 400MB
数据类型:Bitmaps
每个用户 id 占用空间:1位
需要存储的用户量:100000000
全部内存量:1 位 * 100000000 = 12.5MB
redis 统计 (HyperLoglog)
应用场景:
统计相关的功能需求,统计网站 PV(PageView 页面访问量),可以使用 Redis 的 incr、incrby (String数据类型)轻松实现
。UV(UniqueVisitor 独立访客)、独立 IP 数、搜索记录数等需要去重和计数的问题如何解决,集合中不重复元素个数的问题称为基数问题。
代码语言:javascript复制数据存储在 MySQL 表中,使用 distinct count 计算不重复个数 # 随着数据不断增加,导致占用空间越来越大
代码语言:javascript复制使用 Redis 提供的 hash、set、bitmaps 数据结构来处理 # 随着数据不断增加,导致占用空间越来越大
代码语言:javascript复制Redis HyperLogLog 是用来做基数统计的算法,HyperLogLog 的优点是:在输入元素的数量或者体积非常非常大时
计算基数所需的空间总是固定的、并且是很小的
代码语言:javascript复制pfadd:添加多个元素
pfadd key element [element ...]
代码语言:javascript复制pfcount:获取多个HLL合并后元素的个数 # 统计一个或者多个key去重后元素的数量
pfcount key1 key2 ...
代码语言:javascript复制pfmerge:将多个HLL合并后元素放入另外一个HLL
pfmerge destkey sourcekey [sourcekey ...]
redis 二维坐标(Geographic)
提供了经纬度设置、查询、范围查询、距离查询,经纬度Hash。(应用场景多)
代码语言:javascript复制geoadd:添加多个位置的经纬度
geoadd key longitude latitude member [longitude latitude member ...]
geoadd china:city 106.50 29.53 chongqing 114.05 22.52 shenzhen#添加重庆、深圳 2个城市的经纬度
代码语言:javascript复制geodist:获取两个位置的直线距离
geodist key member1 member2 [m|km|ft|mi]
geodist china:city beijing chongqing km #获取北京到重庆的直线距离
代码语言:javascript复制georadius:以给定的经纬度为中心,找出某一半径内的元素
georadius key longitude latitude radius m|km|ft|mi
georadius china:city 110 30 1000 km #在china:city中检索:以经纬度
(110,30)为中心,半径为1000km内的位置列表