Redis教程(2)常用数据类型与数据管理
一、Redis 数据类型
Redis最核心的5种数据类型是字符串(Strings)、哈希(hash)、列表(list)、集合(set)、有序集合(sorted set),除此之外还有高级数据类型位图(Bitmap)、HyperLogLog、地理位置(Geo),其中字符串类型是最简单、使用也最广泛的数据类型。
· 字符串类型
字符串数据类型可以用于多种场景,但是单个Key的值不能超过512M。通常运用于分布式系统session会话缓存共享、浏览计数器等,比如直播时的浏览量就可以使用incr、decr来实现,刷礼物时通过incrby命令来实现。字符串类型有点万金油,但是由于它需要额外的空间来记录数据长度、内存使用等元数据,当实际保存的数据本身很小时,元数据的空间开销反而显得就很大了
· Hash类型
常当作数据库缓存使用,如商品购物车、用户或者产品的详情信息。哈希类型的数据适合存储对象,其数据结构有点像MySQL表中的一行数据,包含了多个字段。MySQL是一张表里存放了多个字段和值,而Redis的Hash类型就是一个key里存放了多个字段和值。由于一个Hash对应一个集合的数据,但是也只使用一个dictEntry来存储元数据,所以会比字符串类型的数据更节省内存空间
· Redis list类型
list列表类型的数据一般用于消息队列(比如使用Redis作为ES的消息队列,当发现ES没有日志进来的时候,可以先看redis消息队列中是否有数据),一个key可以拥有多个value,且值可重复
· Redis集合
分为了有序集合(zset)和无序集合(set),集合内的元素都不可重复。无序集合通过交集、差集或并集获得需要的数据,常用于社交软件共同好友、微博圈子。区别在于有序集合的每一个成员都关联一个评分(score),可以根据这个评分对集合中的成员进行排序,成员虽然是唯一的,但是评分可以重复,常用于做排行榜场景。
· HyperLogLog
该数据类型主要用于对一些海量数据进行统计,并且只会消耗少量的空间(12K的空间可以统计出2^64的数据)。比如统计数千万级别的访问请求中的独立IP数
· GEO类型
该数据类型根据设置的经纬度可以算出地理位置信息以及不同位置的距离,还可以统计出某范围内的成员,比如很多APP上附近的人就可以用该功能实现,而经纬度信息可以通过百度地图等工具进行查询
二、Redis 客户端使用
Redis 自带了命令行客户端工具 redis-cli,通过该工具可以连接 Redis 并进行相关服务管理、数据操作
redis-cli 常用选项介绍
· -h:指定redis的地址,域名或者ip都可以
· -p:指定redis的端口
· -n:指定需要连接的数据库编号
· -a:如果redis配置了密码需要使用该选项指定密码
· -r:指定命令执行的次数
redis-cli -r 3 ping #ping 三次
· -i:和r结合使用,指定多次命令执行的时间间隔,单位为秒
· --bigkeys:找到内存占用比较大的Key,如果是String类型是输出最大 bigkey 的字节长度、对于集合类型来说会输出最大 bigkey 的元素个数。该命令会扫描数据库来进行查找,对 Redis 性能有一定影响,建议在从节点上执行该命令或者使用 -i 参数控制扫描间隔,避免长时间扫描降低 Redis 实例的性能。这个方法只能返回每种类型中最大的那个 bigkey,无法得到大小排在前 N 位的 bigkey,对于集合类型来说只统计集合元素个数的多少,而不是实际占用的内存量
./redis-cli --bigkeys -------- summary ------- Sampled 32 keys in the keyspace! Total key length in bytes is 184 (avg len 5.75) //统计每种数据类型中元素个数最多的bigkey Biggest list found 'product1' has 8 items Biggest hash found 'dtemp' has 5 fields Biggest string found 'page2' has 28 bytes Biggest stream found 'mqstream' has 4 entries Biggest set found 'userid' has 5 members Biggest zset found 'device:temperature' has 6 members //统计每种数据类型的总键值个数,占所有键值个数的比例,以及平均大小 4 lists with 15 items (12.50% of keys, avg size 3.75) 5 hashs with 14 fields (15.62% of keys, avg size 2.80) 10 strings with 68 bytes (31.25% of keys, avg size 6.80) 1 streams with 4 entries (03.12% of keys, avg size 4.00) 7 sets with 19 members (21.88% of keys, avg size 2.71) 5 zsets with 17 members (15.62% of keys, avg size 3.40)
· --latency:检查redis服务的网络延迟,可以用来查看Redis延迟峰值,分析性能问题
· --latency-histrory:以15秒为间隔显示多条网络延迟信息
redis-cli --latency-histrory
· --stat:实时获取redis重要统计信息,虽然统计信息没有info全面,但是能实时看到增量变化
· --raw:将返回的数据格式化再输出,常用于显示包含中文的Key,当key包含了中文时,登陆Redis增加该选项就可以正确获取到中文,否则是二进制格式
三、Redis 管理命令
· keys:列出符合匹配条件的key,支持通配符,如keys *,但是需要注意如果Key数量特别多的话会导致服务阻塞,建议在从节点执行或者使用scan命令
· type:查看指定key的类型,比如是string还是hash
· exists:查看指定key是否存在,存在返回1,否则为0
· randomkey:返回一个随机Key
· ttl:查看指定Key的有效期,-1代表不过期,-2代表键不存在,其他数字代表距离过期秒数
ttl name
· expire / expireat:设置指定Key的有效期,单位为秒,expireat为时间戳格式
expire name 100
· persist:设置指定Key永不过期
persist name
· del:删除一个或多个key,返回的值是成功删除的个数,如果删除的键不存在返回0。删除Bigkey会有阻塞风险
del key1 key2
· renamenx:修改key的名字,只不过新的key名必须是不存在的才可以,避免覆盖已有的key
· unlink:4.0以上版本所支持新的删除Key方法,不会有阻塞问题
· rename:修改key的名字
rename oldkey newkey
· 命令别名:Redis提供了命令别名的功能,可以把默认命名修改或禁用以增强安全性,如果发现命令无法执行需要检查配置文件中是否配置了命令别名
#将FLUSHALL命令禁用 rename-command FLUSHALL ""
· ping:查看服务是否正常连接,如果正常的话会返回一个pong的输出
· select:选择指定编号的数据库。Redis提供了0-15号数据库,默认是0,但是不推荐使用多个数据库来区分业务,真有这种需求的话考虑多实例更好
select 1 #选择1号数据库
· info:获取服务相关统计信息,如Redis版本的查看,占用的内存等,和keys命令一样可以通配符
· memory usage:4.0开始支持,用于查看制定key占用的内存,单位是字节
memory usage test_key
· client list:查看已连接的客户端
· config get:根据匹配条件查看服务配置信息,支持通配符
config get timeout #查看配置文件中timeout相关信息 config get requ* #查看requ开头的配置项
· config set:在线修改redis配置,结合config rewrite可以实现不重启服务而修改配置
config set maxmemory 1gb #在线修改内存大小,支持各种单位
· config rewrite:将在线配置写入到配置文件,不用重启服务
#在线修改redis最大内存 127.0.0.1:6379> config get maxmemory 1) "maxmemory" 2) "24000000000" 127.0.0.1:6379> config set maxmemory 26000000000 OK 127.0.0.1:6379> config get maxmemory 1) "maxmemory" 2) "26000000000" 127.0.0.1:6379> config rewrite OK
· flushdb:删除当前选中库中的所有key,数据量大的时候有阻塞风险
· flushall:删除所有库中的所有key,数据量大的时候有阻塞风险
· dbsize:返回当前库中key的数量
· save:将redis数据持久化存储到rdb文件,由于是前台运行会产生阻塞
· bgsave:开启子现成进行数据持久化,不会阻塞
· shutdown:优雅关闭redis
redis-cli -a 123456 -h 127.0.0.1 shutdown
四、Redis 数据操作命令
字符串
· set:创建Key并赋值,区分大小写,可以非交互写入
set site ywpie.com #设置一个key,名为“site”,值为ywpie.com redis-cli -h 192.168.100.10 -p 6379 set name tom #非交互式设置或读取key
· get:获取指定Key的值
get site #获取之前设置的“site”的值
· setnx: 创建Key并赋值,但是会先判断该Key是否已经存在,已存在返回0失败,避免覆盖已有数据
· setex:给某个key设置一个值,并且指定一个有效期
setex name 10 tanglu #10秒过期
· getset:获取一个key的旧值,并赋予新值
getset name tom #如name旧值为jerry,那么会打印出来,并且重新设置为to
· mset / mget:批量设置和获取多个key,命令复杂度属于O(N),如果获取的元素个数不是特别多的话可以使用,通过批量操作节约网络带宽。该操作属于原子性操作,在批量设置key时如果有一个key失败,整个操作都会失败
mset name1 tom name2 jerry name3 john
· incr / decr:对指定整数型的Key进行自增自减,应用场景比如微博转发增加次数
· incrby / decrby:对指定整数型的Key进行指定数值的增加或减少
Hash
· hset:设置Redis Hash Key
# hset key field value # hsetnx key field value # hmset key field1 value1 field2 value2 hset student1 name tanglu age 30 #设置一个hash key,名为student1,然后添加了name和age两个字段 hset student1 sex male #新增一个sex字段,值位male hmset student1 height 175 weight 70 #一次新增多个字段
· hlen:获取Redis Hash Key元素个数
# hlen key hlen tanglu #显示结果为4,因为上面示例设置了age sex height weight一共4个字段
· hget:获取指定字段的值,get的时候必须写清楚表名和字段名
# hmget key field1 field2 #获取多个值 hget student1 name
· hgetall:获取Hash Key所有字段的值,同keys命令一样需谨慎使用
hgetall key #显示出该Hash类型的key下的所有字段和值,谨慎使用 hkeys key #仅显示该Hash类型的key下的所有字段 hvals key #和上一步相反,显示的是具体的值
· hdel:删除Hash Key中指定的字段和值
hdel key field1 field2...
· hexists:判断Hash Key字段是否存在,返回1代表存在,0代表不存在
hexists key field #一次只能跟一个字段 hexists student1 address
无序集合
sadd ages 25 sadd ages 30 sadd ages 32 sadd ages 25 #重复定义,会添加失败 smembers ages #显示集合中的元素,由于是无序的,不用再指定序号 srem ages 25 #移除一个元素 sismember ages 30 #检查集合中有没有30这个元素
集合
zadd students_top3 tanglu 100 zhangsan 90 lisi 85 zrange students_top3 0 -1 #会根据评分对成员自动排序 zrank students_top3 tanglu #返回1,因为分数排名第一
GEO
#设置2个包含经纬度的key geoadd site 116.404269 39.913411 tiananmen #设置了tiananmeng的经纬度 geoadd site 116.36 39.922461 yuetangongyuan #查询 geopos site tiananmen #距离计算,可选m或km等单位 geodist site tiananmen yuetangongyuan km
列表
lpush names tanglu #从左边开始插入数据 lpush names tom lpush names tanglu #故意定义了重复的value lrange names 0 -1 #获取列表里的全部值,0和-1是起始和结束范围,后进入的key的值反而是在前面的 lrange names 0 1 #获取第一个和第二个值 lrem names 1 tanglu #移除一个值为tanglu的列,这里将会按照序号移除。如果要移除所有的话,序号写0 lpop names #按照后进先出的方式读取列表里的数据,可当做消息队列 rpop names #先进先出 del names #删除列表 blpop #lpop的阻塞版本,当给定列表内没有任何元素可供弹出的时候,连接将被阻塞,直到有另一个客户端对该key执行LPUSH或RPUSH
文章评论