Redis01-数据类型

Redis01-数据类型

1.Redis下载、安装和启动

  1. https://redis.io/,Redis官网;http://www.redis.cn/,Redis中文文档地址。

  2. http://www.redis.cn/download.html,Linux版Redis下载地址;https://github.com/MicrosoftArchive/redis/releases,Windows版Redis下载地址。

  3. Windows上Redis的安装和启动。

    1. 直接解压下载的包,然后双击运行redis-server.exe,或者执行redis-server.exe redis.windows.conf通过配置文件启动。
    2. 双击运行redis-cli.exe,使用客户端到Redis服务,或者执行redis-cli.exe -h 127.0.0.1 -p 6379连接指定的服务器。
  4. Linux上Redis的安装和启动。

    1. 将Redis压缩包上传到opt目录,然后tar -zxvf redis-6.0.6.tar.gz解压。
    2. yum install gcc-c++,安装编译软件。
    3. 进入解压后的Redis包中,执行make命令进行安装,安装时gcc版本低的解决方法。
    # 将命令窗口的gcc版本临时升级到9.3.1-2
    yum -y install centos-release-scl && yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils && scl enable devtoolset-9 bash
    
    # 永久升级gcc到9.3.1-2
    echo "source /opt/rh/devtoolset-9/enable" >>/etc/profile
    
    1. make install,确认是否安装成功。
    2. Redis的默认安装路径,/usr/local/bin
    3. Redis的启动。默认前后启动,需要redis.conf中的daemonize no修改为daemonize yes,让其后台启动;redis-server redis.conf,通过配置文件启动。
    4. redis-cli -p 6379 -h 127.0.0.1,通过Redis客户端连接指定的Redis服务。
  5. Redis后台启动后,在Redis客户端中执行shutdown命令关闭Redis服务,exit退出客户端连接。

2.Redis压力测试

  1. 在Redis的安装目录执行redis-benchmark -h 127.0.0.1 -p 6379 -c 50 -n 100000进行压力测试。-c,创建50个客户端连接;-n,100000个请求。
  2. 压力测试结果的分析。
====== SET ======
100000 requests completed in 2.51 seconds # 100000个请求
50 parallel clients # 50个客户端连接
3 bytes payload # 每次写入3个字节
keep alive: 1 # 一个服务器可用
host configuration "save": 900 1 300 10 60 10000 # save规则
host configuration "appendonly": no # AOF
multi-thread: no

73.04% <= 1 milliseconds # 1毫秒处理了73.04%的请求

3.Redis基础知识和命令

  1. Redis有16个数据库,默认连接第0个数据库,每个数据库之间的数据相互隔离。即在第一个数据库保存的数据,只能在第一个数据中查询到,不会在第二个数据库中查询到。
  2. select 3,切换到第3个数据库。
  3. dbsize,查看当前数据库已保存数据的大小。
  4. flushdb,清空当前数据库;flushall,清空所有数据库。
  5. keys *,查看所有的key。
  6. Redis单线程却依然高效的原因。
    1. Redis是基于内存的操作,比起基于磁盘的操作,就会快很多。因此CPU不是Redis的瓶颈,单线程足以,而内存和网络是Redis的瓶颈。
    2. 使用多线程就需要考虑多线程安全的问题,而且多线程时CPU上下文的线程切换也会有一定的性能消耗。

4.Redis数据结构-String

rename name usename # 重命名key
	
set name tom # 保存key
get name # 查看key值
exists name # 查看key是否存在
type name # 查看key的类型

expire name 10 # 设置name 10秒过期
ttl name # 查看key过期时间。-1,当前key没有设置过期时间;-2,当前key设置过期时间,但是已经过期了。

del name # 删除key

move name 1 # 将name移动到1号数据库

strlen name # 查看key对应value的长度
append name app # 如果key存在,就给key的value追加值,如果不存在就set key。

incr name # name自增1
decr name # name自减1
incrby name 10 # name自增10
decrby name 5 # name自减5

getrange name 0 -1 # 获取name对应的value的指定范围的索引的字符。包含头,包含尾

set name 'hello world'
getrange name 0 1 # "he"

set name 'hello world' 
setrange name 2 1234 # 字符串替换,"he1234world"

set name tom nx # 当name没有值时才能成功,如果name有值,则直接失败
setnx name tom # 同set name tom nx

mset k1 v1 k2 v2 # 一次性设置多个值

mget k1 k2 # 一次性获取多个值

set name tom ex 20 # 设置key20秒过期
setex name 10 tom # 同set name tom ex 20

persist name # 去除key的过期时间

getset name1 k # 先获取值,在修改值。如果值存放,返回之前之前的值;如果值不存在,返回null。

String类型的应用。 
set user:1 '{"name":"tom","age",10}' # 将id=1的用户信息,用过json保存到Redis中。

5.Redis数据结构-List

lpush name n1 # 往list的头部插入值
rpush name n2 # 往list的尾部插入值

lrange name 0 -1 # 获取list的值,从左到右

lpop name # 弹出队列头部的值
rpop name # 弹出队列尾部的值

lindex name 0 # 获取name队列索引为0的值。
llen name # 获取list的长度

lrem name 2 n1 # 移除list中两个n1的值,从左到右一次移除两个value=n1值。
ltrim name 1 3 # 保留list中索引1到索引3处的值,含头含尾。

rpoplpush name name01 # 弹出name中的尾部的值,并将这个值放入到name01的头部。

lset name 0 n1 # 将name列表中索引为0的地方处的值,更新为n1,如果列表或者索引处没有值,则报错。
(error) ERR no such key # 列表不存在
(error) ERR index out of range # 列表存在,但是索引处没有值。

linsert name before n1 t1 # 往name列表的n1值前插入t1值。
linsert name after n1 t2 # 往name列表的n1值后插入t2值。

# 使用Redis作为生产和消费者模型,指定消费者等待的超时时间。
blpop name 1 # 如果队列为空,值等待一秒钟,并在1秒钟后返回null。(nil)

6.Redis数据结构-Set

sadd name n1 # 往sadd中加入值
smembers name # 获取name中的所有值。

sismember name n3 # 查看name中n3值是否存在,存放返回1,不存在返回0。
scard name # 查看set的大小

srem name n1 # 移除set中的n1
srandmember name 2 # 随机获取set中的两个值。

spop name # 随机移除set中的值。
smove name1 name2 n1 # 将name1值n1中移动到name2中。

sdiff k1 k2 # 两个set的差集
sinter k1 k2 # 两个set的交集
sunion k1 k2 # 两个set的并集。

7.Redis数据结构-Hash

hset name k1 v2 # name中存入值
hget name k1 # name中获取值

hgetall name # 获取name中的所有哈希值。

hmset name n1 t1 n2 t2 # 往name中存入多个值。
hget name k1 k2 # 获取多个值。

hdel name k1 # 删除哈希中的值。

hlen name # 获取name中有多少个键值对。
hexists name k2 # 判断哈希中的key是否存在。

hkeys name # 获取所有的key
hvals name # 获取所有的value

hincrby name n1 3 # 将n1的值增加3

8.Redis数据结构-ZSet

zadd name 1 k1 2 k2 # 添加值,每个值带分数,1和2为值的分数。
		
zrange name 0 -1 # 获取zset中的值。

zrangebyscore name -inf +inf # 获取zset指定范围的值,-inf,负无穷 +inf,正无穷

zrangebyscore name -inf +inf withscores # 获取zset指定范围的值,按照score从小到大排序。
zrevrange name 0 -1 # 倒序列表,获取zset中的值。按照score从大到小排序。

zrem name k1 # 删除zset中的值
zcard name # 计算zset的大小。

zcount name 1 2 # 统计score在1-2中间的值的数量

9.Redis数据结构-Geospatial

# 有效的经度从-180度到180度。
# 有效的纬度从-85.05112878度到85.05112878度。
	
geoadd city 125.14 42.92 xianan # geoadd keyname 经度 纬度 城市名
geoadd city 104.06 30.65 chengdu
geoadd city 120.25 30.28 hangzhou
geoadd city 116.40 39.90 beijing
geoadd city 121.47 31.23 shanghai
geoadd city 114.08 22.54 shenzhen

geopos city shanghai beijing # 获取经纬度值。

geodist city shanghai beijing km # 查询两个城市直接的距离 "1067.3788"
# 显示的单位	
- m 表示单位为米。
- km 表示单位为千米。
- mi 表示单位为英里。
- ft 表示单位为英尺。

# 以为100经度,30纬度为中心,查询半径1000KM内城市
georadius city 100 30 1000 km
# withdist 显示城市到中心点的直线距离,withcoord显示查询到城市的经纬度,asc 升序排列
# count 10,只查询10个。
georadius city 110 30 1000 km withdist withcoord count 10 asc
	
# georadiusbymember,以北京为中心查找附加1000KM的城市。
georadiusbymember city beijing 1000 km withdist withcoord count 10 desc withdist
	
geohash city beijing xianan # 返回城市经纬度对应的11位的哈希值,城市距离越近,哈希值越相似。
	
# geodist底层使用 zset实现,所以可以使用 zrange city 0 -1查看所有的城市。
zrange city 0 -1 withscores # 显示城市在zset的中分数。按照分数升序排列。
zrem city chengdu # 删除城市。

10.Redis数据结构-Hyperloglog

# hyperloglog基数计算 
# 如A = {1 2 3 4 5},hyperloglog查看A中不重复的元素的个数。
# hyperloglog占用非常小的内存,但是统计数量的元素个数是个近似值,有一定的误差。

pfadd num1 1 2 3 4 5 6 7 7
pfcount num1 # 查看num1中不重复元素的个数
		
pfmerge num3 num1 num2 # 将num1和num2中的元素合并为num3。num3中元素不重复;num1和num2在合并后依然存在。

11.Redis数据结构-Bitmaps

# Bitmaps 位图,只能保存0和1

setbit flag 1 0 # 设置周一的状态为0
setbit flag 2 1 # 设置周二的状态为0

getbit flag 1 # 获取周一的状态

bitcount flag # 查询flag中状态是1的个数。

12.Redis事务

  1. Redis单条命令执行保证原子性,但是Redis事务不保证原子性。
  2. Redis会将事务添加到一个队列中,当发起exec执行指令的时候,会按照添加事务的顺序进行事务的执行。
  3. 因为 Redis是单线程的,所以不需要考虑事务之间的隔离性。
  4. Redis事务相关的命令
# 事务的正常操作
multi # 开始事务
set k1 v2
exec # 执行事务

# discard放弃事务
multi # 开启事务
set k3 v3
discard # 事务的执行
  1. 事务异常操作,命令格式错误,所有的命令都不执行。
multi
set k1 v1
getset k1 # 命令错误
(error) ERR wrong number of arguments for 'getset' command
set k2 v2
exec # 命令错误,所有命令格式都不执行。
# 命令格式错误,执行exec的错误信息
(error) EXECABORT Transaction discarded because of previous errors.
  1. 事务异常操作,命令格式正确,运行错误,错误命令不执行,其他命令执行
multi
set k1 v1
incr k1 # 对String自增一
set k2 v2
exec 
# exec执行结果
1) OK
2) (error) ERR value is not an integer or out of range # 第二条命令执行错误,但是不影响其他命令的执行。
3) OK

13.Redis乐观锁-sh

watch money # 监视money,只在开启事务的时候对money的修改有监视的作用。
multi
incrby money 10
exec # 在当前线程窗口中执行exec的时候,其他线程创建将money的值进行了修改,exec将执行失败,返回null。
# 错误的返回结果
(nil)

# 错误的处理方法
unwatch # 当事务提交失败,需要先放弃money的监视,然后重新 watch money监控,在执行事务。

14.Redis脚本执行

# script 执行的脚本
# numkeys key的数量
#[key ...] key值
# [arg ...] 参数
# 脚本执行的命令格式 EVAL script numkeys key [key ...] arg [arg ...]

# 返回k1和v1、k2和v2的值。
eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 "k1" "k2" "v1" "v2"

# 执行mget,查询k1、k2和k3的值。
eval "return redis.call('mget', 'k1', 'k2', 'k3')" 0
posted @ 2021-11-21 19:54  行稳致远方  阅读(38)  评论(0)    收藏  举报