前言:
做开发几年了,期间也接触过几种NoSql数据库,比如redis、mongodb、memcache等。但是一直没有很好的、系统的和全面的梳理过它们的知识点。
今天,我就从Redis开始,先做一个关于redis的系列文章。主要包括以下部分:
1.Redis的安装、基本数据结构、python客户端、pub/sub命令
2.数据结构的实现、内存管理、php客户端、高级特性Geo
3.RDB持久化、AOF持久化、Java客户端、高级特性HyperLogLog
4.哨兵、集群以及结合devops
5.……
本篇文章就先从第1个开始。
1
本文主要讲解redis在liunx上的安装,windows上的redis安装暂时不在本文的讨论范围。
1.yum安装
1) yum命令直接安装
yum install -y redis
2) 查看redis版本
redis-cli –version
3) 重启redis
systemctl restart redis
4) 设置开机自动启动redis
systemctl enable redis
5) 打开远程访问
vim /etc/redis.conf
6) 连接redis
redis-cli
2.apt-get安装
1) apt-get命令直接安装
apt-get installredis-server
2) dpkg-query查看redis安装的相关文件
dpkg-query -Lredis-server
3) 查看redis版本
redis-cli–version
4) 重启redis
systemctl restartredis
5) 设置开机自动启动redis
systemctl enableredis
6) 打开远程访问
vim/etc/redis/redis.conf
7) 连接redis
redis-cli
3.编译安装
2
1、字符串类型:是Redis最简单的数据结构,与python中的字符串类似。
命令 |
作用 |
备注 |
GET | 获取指定key的值 | GET key |
SET | 设置指定key的值 | SET key value value如果有空格需要加引号 |
MGET | 获取多个键值 | MGET key [key …] |
MSET | 设置多个键值 | MSET key value [key value …] |
INCR | 整数递增 | INCR key |
INCRBY | 增加指定的整数 | INCRBY key increment |
INCRBYFLOAT | 增加指定的浮点数 | INCRBYFLOAT key increment |
DECR | 整数递减 | DECR key |
DECRBY | 减少指定的整数 | DECRBY key increment |
APPEND | 向尾部追加值 | APPEND key value |
STRLEN | 获取字符串长度 | STRLEN key |
GETBIT | 获取二进制位置值 | GETBIT key offset |
SETBIT | 设置二进制位置值 | SETBIT key offset value |
BITCOUNT | 二进制是1的个数 | BITCOUNT key [start end] |
BITOP | 位运算 | BITOP operation destkey key [key …],operation支持AND、OR、XOR、NOT |
BITPOS | 偏移 | BITPOS key bit [start] [end] |
2、hash类型:类似于python中的dict,一个key对应一个value。注意,redis中hash的值只能是字符串。
命令 |
作用 |
备注 |
HSET | 设置单个 | HSET key field value,不存在时返回1,存在时返回0 |
HGET | 读取单个 | HGET key field,不存在是返回nil |
HMSET | 设置多个 | HMSET key field value [field value …] |
HMGET | 读取多个 | HMGET key field [field …] |
HGETALL | 读取全部 | HGETALL key,返回时字段和字段值的列表 |
HEXISTS | 判断字段是否存在 | HEXISTS key field,存在返回1,不存在返回0 |
HSETNX | 字段不存在时赋值 | HSETNX key field value,与hset命令不同,hsetnx是键不存在时设置值 |
HINCRBY | 增加数字 | HINCRBY key field increment,返回增加后的数,不是整数时会提示错误 |
HDEL | 删除字段 | HDEL key field [field …] ,返回被删除字段的个数 |
HKEYS | 只获取字段名 | HKEYS key,返回键的所有字段名 |
HVALS | 只获取字段值 | HVALS key,返回键的所有字段值 |
HLEN | 字段数量 | HLEN key,返回字段总数 |
3、列表类型:类似于python中的list,用pop和push的方式输入和输出元素,是消息队列的首要选择。
命令 |
作用 |
备注 |
LPUSH | 添加左边元素 | LPUSH key value [value …] |
LPOP | 移除左边第一个元素 | LPOP key |
RPUSH | 添加右边元素 | RPUSH key value [value …] |
RPOP | 移除右边第一个元素 | RPOP key |
LLEN | 列表元素个数 | LLEN key |
LRANGE | 获取列表片段 | LRANGE key start stop |
LREM | 删除指定值 | LREM key count value |
LINDEX | 索引元素值 | LINDEX key index |
LSET | 设置元素值 | LSET key index value |
LTRIM | 保留列表片段 | LTRIM key start stop,start、top |
RPOPLPUSH | 列表转移 | RPOPLPUSH source desctination,从source列表转移到desctination列表 |
4、集合类型:类似于python中的set,内部的键值是无序且唯一的。
命令 |
作用 |
备注 |
SADD | 添加元素 | SADD key member [member …] |
SREM | 删除元素 | SREM key member [member …] |
SMEMBERS | 获取全部元素 | SMEMBERS key |
SISMEMBER | 判断值是否存在 | SISMEMBER key member |
SDIFF | 差运算 | SDIFF key [key …] |
SINTER | 交运算 | SINTER key [key …] |
SUNION | 并运算 | SUNION key [key …] |
SCARD | 集合元素个数 | SCARD key |
SDIFFSTROE | 差运算并存储到新集合中 | SDIFFSTROE destination key [key …] |
SINTERSTROE | 交运算并存储到新集合中 | SINTERSTROE destination key [key …] |
SUNIONSTROE | 并运算并存储到新集合中 | SUNIONSTROE destination key [key …] |
SRANDMEMGER | 随机获取元素 | SRANDMEMBER key [count] |
SPOP | 弹出元素 | SPOP key [count] |
5、有序集合类型:是redis中最有特色的数据结构,一方面它是一个set,另一方面它可以给每个value赋予一个score,代表这个value的排序权重。
命令 |
作用 |
备注 |
ZADD | 添加集合元素 | ZADD key [NX|XX] [CH] [INCR] score member [score member …] |
ZSCORE | 获取元素分数 | ZSCORE key member |
ZRANGE | 元素小到大 | ZRANGE key start top [WITHSCORES] |
ZREVRANGE | 元素大到小 | ZREVRANGE key start [WITHSCORES] |
ZRANGEBYSCORE | 指定分数范围元素,从小到大 | ZRANGEBYSCORE key min max [WITHSCORE] [LIMIT offest count] |
ZREVRANGESCORE | 指定分数范围元素,从大到小 | ZREVRANGEBYSCORE key max min [WITHSCORE] [LIMIT offest count] |
ZINCRBY | 增加分数 | ZINCRBY key increment member |
3
Python操控redis,需要安装python的redis模块。很简单,使用pip的方式安装:pip install redis。
1、python连接redis的方式,分两种:
1)直接连接
r = redis.Redis(host=’localhost’, port=6379,decode_responses=True)
2)连接池连接
pool = redis.ConnectionPool(host=’localhost’,port=6379, decode_responses=True)
r = redis.Redis(connection_pool=pool)
2、使用举例
如下图所示,下图代码就是python调用redis的一个简单示例。其中set函数为创建一个key为name,value为tiops的字符串类型,若存在则修改。get函数为获取该字符串的值。
Redis的函数就不一一讲解了,下面有其总结。
1)公共操作
函数 |
备注 |
delete(*names) | 删除 |
expire(name ,time) | 设置超时时间 |
exists(name) | 检查名字是否存在 |
keys(pattern=”) | 模糊匹配 |
rename(src, dst) | 重命名 |
type(name) | 获取类型 |
randomkey() | 随机获取name |
scan(cursor=0, match=None, count=None) | 查看所有元素 |
scan_iter(match=None, count=None) | 查看所有元素–迭代器 |
2)字符串类型
函数 |
备注 |
set(name, value, ex=None, px=None, nx=False, xx=False) | 设置值,在就创建,不在修改。
ex,过期时间(秒) px,过期时间(毫秒) nx,如果设置为True,则只有name不存在时,当前set操作才执行 xx,如果设置为True,则只有name存在时,当前set操作才执行 |
setnx(name, value) | 设置值,只有name不存在时,执行设置操作 |
setex(name, value, time) | 设置值,并设置过期时间,time单位秒 |
psetex(name, time_ms, value) | 设置值,并设置过期时间,time_ms单位毫秒 |
mset(args, *kwargs) | 批量设置值 |
mget(keys, *args) | 批量获取值 |
getset(name, value) | 设置新值并获取原来的值 |
getrange(key, start, end) | 获取指定范围内的值 |
setrange(name, offset, value) | 修改指定范围内的值 |
setbit(name, offset, value) | 对name对应值的二进制进行位操作 |
getbit(name, offset) | 获取name对应的值的二进制表示中的某位的值 (0或1) |
bitcount(key, start=None, end=None) | 获取name对应的值的二进制表示中1的个数 |
bitop(operation, dest, *keys) | 获取多个值,并将值做位运算,将最后的结果保存至新的name对应的值 |
strlen(name) | 返回name对应值的字节长度(一个汉字3个字节) |
incr(self, name, amount=1) | 自增name对应的值(增加整数) |
incrbyfloat(self, name, amount=1.0) | 自增name对应的值(增加浮点数) |
decr(self, name, amount=1) | 自减name对应的值(减少整数) |
append(key, value) | 值后面追加内容 |
3)Hash类型
函数 |
备注 |
hset(name, key, value) | 对应的key设置一个value |
hsetnx(name, key, value) | 对应的key设置一个value,不存在才执行 |
hmset(name, mapping) | 批量增加 |
hget(name,key) | 根据key获取value |
hmget(name, keys, *args) | 获取多个key的值 |
hgetall(name) | 取出所有的键值对 |
hlen(name) | 获取键值对的个数 |
hkeys(name) | 获取所有的key的值 |
hvals(name) | 获取所有的value的值 |
hexists(name, key) | 检查是否存在当前传入的key |
hdel(name,*keys) | 将指定key的键值对删除 |
hincrby(name, key, amount=1) | 自增指定key的值,整数 |
hincrbyfloat(name, key, amount=1.0) | 自增指定key的值,浮点数 |
hscan(name, cursor=0, match=None, count=None) | 增量式迭代获取,对于数据大的数据非常有用,hscan可以实现分片的获取数据,并非一次性将数据全部获取完 |
hscan_iter(name, match=None, count=None) | 利用yield封装hscan创建生成器,实现分批去redis中获取数据 |
4) 列表类型
函数 |
备注 |
lpush(name,values) | 从左边增加,没有的话就创建 |
lpushx(name,value) | 从左边增加,没有的话无法创建 |
rpush(name,values) | 从右边增加,没有的话就创建 |
rpushx(name,value) | 从右边增加,没有的话无法创建 |
linsert(name, where, refvalue, value)) | 在name对应的列表的某一个值前或后插入一个新值 |
lset(name, index, value) | 指定索引号进行修改 |
lrem(name, value, num) | 指定值进行删除 |
lpop(name) | 删除并返回 |
ltrim(name, start, end) | 删除索引之外的值 |
lindex(name, index) | 根据索引取值 |
rpoplpush(src, dst) | 元素从一个列表移动到另一个列表 |
brpoplpush(src, dst, timeout=0) | 元素从一个列表移动到另一个列表,设置超时 |
blpop(keys, timeout) | 一次移除多个列表 |
5) 集合类型
函数 |
备注 |
sadd(name,values) | 新增 |
scard(name) | 获取元素个数 |
smembers(name) | 获取集合中所有的成员 |
sdiff(keys, *args) | 差集 |
sdiffstore(dest, keys, *args) | 差集并存到一个新的集合中 |
sinter(keys, *args) | 交集 |
sinterstore(dest, keys, *args) | 交集并存到一个新的集合中 |
sunion(keys, *args) | 并集 |
sunionstore(dest,keys, *args) | 并集并存到一个新的集合 |
sismember(name, value) | 判断是否是集合的成员 |
smove(src, dst, value) | 移动 |
spop(name) | 随机删除并且返回被删除值 |
srem(name, values) | 指定值删除 |
6) 有序集合类型
函数 |
备注 |
zadd(name, args, *kwargs) | 新增 |
zcard(name) | 获取有序集合元素个数 |
zrange( name, start, end,desc=False, withscores=False, score_cast_func=float) | 按照索引范围获取name对应的有序集合的元素 |
zrevrange(name, start, end, withscores=False, score_cast_func=float) | 按照索引范围获取name对应的有序集合的元素,从大到小排序 |
zrangebyscore(name, min, max,start=None, num=None, withscores=False, score_cast_func=float) | 按照分数范围获取name对应的有序集合的元素 |
zrevrangebyscore(name, max, min,start=None, num=None, withscores=False, score_cast_func=float) | 按照分数范围获取name对应的有序集合的元素,从大到小排序 |
zscan(name,cursor=0, match=None, count=None, score_cast_func=float) | 获取所有元素 |
zscan_iter(name,match=None, count=None,score_cast_func=float) | 获取所有元素–迭代器 |
zcount(name, min, max) | 获取name对应的有序集合中分数在min,max之间的个数 |
zincrby(name, value, amount) | 自增 |
zrank(name, value) | 获取值的索引号 |
zrevrank(name, value) | 获取值的索引号,从大到小排序 |
zrem(name, values) | 指定值删除 |
zremrangebyrank(name, min, max) | 根据索引号删除 |
zremrangebyscore(name, min, max) | 根据分数范围删除 |
zscore(name, value) | 获取值对应的分数 |
4 我们生活中的订阅功能就是由pub/sub功能实现的,最简单的例子:您订阅了我们新钛云服的公众号,等我们新钛云服公众号发送新文章时,就会第一时间通知您。
道理相同,redis中pub/sub也是一种实现Pub/Sub功能的方式。了解redis的pub/sub之前,我们要先清楚Pub/Sub功能的定义:
Pub/Sub功能(meansPublish, Subscribe)即发布及订阅功能。基于事件的系统中,Pub/Sub是目前广泛使用的通信模型,它采用事件作为基本的通信机制,提供大规模系统所要求的松散耦合的交互模式:订阅者(如客户端)以事件订阅的方式,表达出它有兴趣接收的一个事件或一类事件;发布者(如服务器)可将订阅者感兴趣的事件随时通知相关订阅者。熟悉设计模式的朋友应该了解这与23种设计模式中的观察者模式极为相似。
1、SUBSCRIBE命令:
该命令的作用,就是让客户端去订阅一个或多个它想要订阅的频道。例如:如下图所示,客户端client1、client2、client3分别订阅了tiopsChannel和tisecChannel频道。
上图中,client1、client2都订阅了tiopsChannel,而client2、client3则都订阅了tisecChannel。
这就是SUBSCRIBE命令的作用,在客户端执行以下语法:
subscribe 频道1 [频道2] [频道3] [频道4] ……
2、PUBLISH命令:
该命令的作用,就是从频道服务端发送一条或多条信息到订阅该频道的客户端处。根据上图做变形,就变成下图所示:
PUBLISH命令语法:
publish 频道1 “信息”
3、命令总结:
命令 |
作用 |
备注 |
SUBSCRIBE | 订阅频道 | SUBSCRIBE channel [channel …] |
UNSUBSCRIBE | 退订频道 | UNSUBSCRIBE channel [channel …] |
PSUBSCRIBE | 正则的方式订阅频道 | PSUBSCRIBE pattern [pattern …] |
PUNSUBSCRIBE | 正则的方式退订频道 | PUNSUBSCRIBE [pattern [pattern …]] |
PUBLISH | 频道推送信息 | PUBLISH channel “message” |
PUBSUB | 查看订阅与发布系统状态 | PUBSUB <subcommand> [argument [argument …]] |