Redis基础
首发于:2021-12-28
NoSQL概述
意为Not Only SQL
为什么需要NoSQL
- High performance - 高并发读写
- Huge Storage - 海量数据的高效率存储和访问
- High Scallability && High Availablility - 高可扩展性和高可用性
主流NoSQL产品
- Redis
- MongoDB
- CouchDB
- Cassandra
- membase
- riak
NoSQL数据的四大分类
- 键值(Key-Value)存储
- 列存储
- 文档数据库
- 图形数据库
NoSQL的特点
- 易扩展
- 灵活的数据模型
- 大数据量,搞性能
- 高可用
Redis概述
高性能键值对数据库,2009年开发,新浪微博,知乎网,GitHub,Stack Overflow,VMware等都在使用。C语言编写。
支持的数据类型
- 字符串(String)
- 列表(List)
- 有序集合(sorted set)
- 集合(set)
- 散列(hash)
应用场景
- 缓存
- 任务队列
- 网站访问统计
- 数据过期处理
- 分布式集群架构中的session分离
Redis的安装
一般来说 Redis 都是在 Linux 下环境下运行,在 Windows 环境下性能会差很多,所以这里我使用的是 Ubuntu 系统来进行安装。
按照要求执行下载和制作操作,例如:
$ wget http://download.redis.io/releases/redis-5.0.5.tar.gz
$ tar xzf redis-5.0.5.tar.gz
$ cd redis-5.0.5
$ make
安装完成之后可以,测试一下
$ make test
输入下面命令来启动redis服务(前端启动)
$ src/redis-server
前端启动方式对于我们测试是否安装成功,或者临时使用是没有问题的,但是对于生产环境就最好是使用后端启动了,下面我们先 Ctrl + c 退出前端启动,输入下面命令来修改一下配置文件
$ vim redis.conf
按 i
进入编辑模式
找到 daemonzie no
,将其改为 daemonize yes
按 Esc
,然后输入 :wq
,再回车保存
输入下面命令,加载配置文件运行
$ src/redis-server ./redis.conf
这时不出意外redis就已经启动起来了,可以执行下面的命令查找redis进程
$ ps -ef | grep -i redis
另一种后台启动的方式是
$ src/redis-server &
执行下面命令可以停止redis服务
$ src/redis-cli shutdown
开启redis之后,输入下面命令就可以连接redis服务了
$ src/redis-cli
避免中文乱码方法
$ src/redis-cli --raw
开启远程访问方法
$ vim redis.conf
行首添加“#” 注释掉 bind 内容
修改 protect-mode yes
为 protect-mode no
如果需要添加密码 将 # requirepass
前面的 “#” 删除
连接远程redis库,命令
$ redis-cli -h host -p port -a password
Mac 安装
# 更新 brew 的镜像地址
$ cd "$(brew --repo)"
$ git remote set-url origin https://mirrors.ustc.edu.cn/brew.git
$ cd "$(brew --repo)/Library/Taps/homebrew/homebrew-core"
$ git remote set-url origin https://mirrors.ustc.edu.cn/homebrew-core.git
# 输入之后 cmd 窗的标题会一直闪,持续几分钟直到更新完毕
$ brew update
# 安装
$ brew install redis
# 启动服务的一种方法
$ brew services start redis
# 配置文件位置 /usr/local/etc/redis.conf
# 启动服务并使用配置文件
# 首先进入安装目录
$ cd /usr/local/bin/
# 启动服务,之后会出现一个经典的 redis 图标
$ redis-server /usr/local/etc/redis.conf
# 其实下面命令也能直接启动redis服务
$ redis-server
# 启动 redis 客户端
$ redis-cli
# 代参数的连接
$ redis-cli -h 127.0.0.1 -p 6379 -n 0 -a pwd
# 可以用下面命令查看
$ redis-cli --help
Redis数据结构
字符串(String)
Key-Value结构,注意:key定义不要过长,尽量不要超过1024 byte 否则会降低查询效率、消耗内存;也不要过短,会降低可读性;最好有统一的命名规范。
String类型是按照二进制存储的,Value最大长度为512MB
# 赋值
set key value
# 取值
get key
# 取值赋值,先获取值再设置值
getset key value
# 删除值
del key
# incr 给一个值加1,如果不能转为整型就报错,如果没有这个key就先置为0,再加1,其它的直接加1
incr key
# decr 给一个值减1,如果不能转为整型就报错,如果没有这个key就先置为0,再减1,其它的直接减1
decr key
# incrby 给指定key加一个数(num)
incrby key num
# decrby 给指定key减一个数(num)
decrby key num
# append 在原值上追加一个字符串,并返回value的长度
append key string
哈希(Hash)
String Key与String Value的Map容器;每一个哈希可以存储4294967295个键值对;
# 赋值
hset key value-field value-value
hset myhash username Jack
hset myhash age 20
# 赋值多个键值对
hmset key value-field1 value-value1 value-field2 value-value2 ...
hmset myhash2 username Rose age 18
# 取值
hget key value-field
hget myhash username
# 获取多个属性的值
hmget key value-field1 value-field2
hmget myhash2 username age
# 获取所有属性值
hgetall key
hgetall myhash
# 删除一个或多个字段
hdel key value-field1 value-field2 ...
hdel myhash2 username age
# 删除键
del key
# 增加数字
hincrby key value-field num
hincrby myhash age 5
# 判断一个属性是否存在
hexists key value-field
hexists myhash username
# 获取字段长度
hlen key
hlen myhash
# 获取所有字段名称
hkeys key
hkeys myhash
# 获取所有的值
hvals key
hvals myhash
列表(List)
按照插入顺序排列的链表,两端插入数据效率高,中间插入数据效率最低。
ArrayList
使用数组方式存储数据
LinkedList
使用双向链接方式存储数据
# 左端添加
lpush key value...
lpush mylist a b c
# 右端添加
rpush key value...
# 查看链表数据,0为开端,-1为结尾
lrange key start end
lrange mylist 0 3
# 左端弹出
lpop key
lpop mylist
# 右端弹出
rpop key
rpop mylist2
# 获取list长度
llen key
llen mylist
# 左端添加(仅存在key时添加)
lpushx key value...
lpushx mylist c d
lpushx mylist3 c d
# 右端添加(仅存在key时添加)
rpushx key value...
rpushx mylist2 c d
rpushx mylist3 c d
# 左端移除key中count个值为value的元素,count为正从左开始count个,count为负右端开始count个,为0则全部移除
lrem key count value
lrem mylist 0 a
# 在指定位置设置值
lset key index value
lset mylist 0 x
# 插入数据
linsert key before value newValue
linsert key after value newValue
linsert mylist before x xbefore
linsert mylist after x xafter
# 从key1一个弹出并添加到key2中,常用于消息队列
rpoplpush key1 key2
rpoplpush mylist mylist2
Set(集合)
和List类型有相似的结构,但是和List不同的是Set中不能出现重复的元素。
可包含的最大元素数量为4294967295
# 添加元素
sadd key value...
sadd myset a b c
# 删除元素
srem key value...
srem myset a b
# 查看值
smembers key
smembers myset
# 判断一个值是否存在,返回1存在,0则不存在
sismember key value
sismenber myset a
# 集合的差集运算
sdiff key1 key2
sadd a1 a b c
sadd b1 a c 1 2
sdiff a1 b1 // 返回b
# 集合的交集运算
sinter key1 key2
sadd a2 a b c
sadd b2 a c 1 2
sinter a2 b2 // 返回a c
# 集合的并集运算
sunion key1 key2
sadd a3 a b c
sadd b3 a c 1 2
sunion a3 b3 // 返回a c 2 b 1
# 获取一个key中值的数量
scard key
scard a1
# 随机返回一个key中的元素
srandmember key
srandmember a1
# 把key2 key3的差集存到key1中
sdiffstore key1 key2 key3
sdiffstore mys a1 b1
# 把key2 key3的交集存到key1中
sinterstore key1 key2 key3
sinterstore mys2 a2 b2
# 把key2 key3的并集存到key1中
sunionstore key1 key2 key3
sunionstore mys3 a3 b3
Sorted-Set(有序集合)
与Set类似,但是是有序的,每个元素都有一个分数,元素在各个位置的查找、删除等操作都很快速。
# 添加元素
zadd key score value
zadd mysort 70 zs 80 ls 90 ww
# 获取分数
zscore key value
zscore mysort zs
# 获取成员数量
zcard key
zcard mysort
# 删除指定元素
zrem key value...
zrem mysort ww
# 范围查找
zrange key start end [withscores]
zrange mysort 0 -1
zrange mysort 0 -1 withscores
# 从大到小排序的范围查找
zrevrange key start end [withscores]
zrevrange mysort 0 -1
zrevrange mysort 0 -1 withscores
# 按照范围删除
zremrangebyrank key start end
zremrangebyrank mysort 0 3
# 按照分数范围删除
zremrangebyscore key start end
zadd mysort 70 zs 80 ls 90 ww
zremrangebyscore mysort 70 80
# 按照分数范围进行查询
zrangebyscore key start end [withscores] [limit start count]
zrangebyscore mysort 70 100
zrangebyscore mysort 70 100 withscores limit 0 1
# 给指定成员增加分数
zincrby key score value
zincrby mysort 3 ls
# 获取某个分数范围内成员的数量
zcount key start end
zcount mysort 70 90
key的通用操作
# 查询所有key
keys *
# 查看某个key,?为通配符
keys my?
keys my????
# 删除key
del key...
del my1 my2 my3
# 判断一个key是否存在,0不存在,1存在
exists key
exists my1
# 重命名key
rename oldkey newkey
rename a b
# 设置key的过期时间,以秒为单位,过期之后该key就不存在了
expire key seconds
expire b 1000
# 查看key剩余的超时时间
ttl key
ttl b
# 获得key的类型
type key
type mylist
type myhash
Redis的特性
多数据库
最多可以提供16个数据库,默认连接0号数据库。
# 选择数据库
select dbIndex
select 1
select 0
# 把一个key从一个数据库移动到另一个数据库
move key dbIndex
move mys 1
事务
与SQL中的事务类似
- multi 开启事务
- exec 提交事务
- discard 回滚事务
# 设置一个num,值为1
set num 1
# 开启事务
multi
# 给num加1,此时去get num ,num还为1
incr num
# 执行事务,此时去get num ,num为2
exec
# 设置一个user,值为Jack
set user Jack
# 开启事务
multi
# 把Jack,改为Tom
set user Tom
# 回滚事务,此时还为Jack
discard
Redis的持久化
把内存中的数据存储到硬盘上,保证数据不丢失,这就是持久化操作。
RDB
默认支持,不需要配置。在指定的时间间隔内,将内存中的数据集快照写入到磁盘。
优势
- 只有一个文件,对于文件备份比较方便
- 性能高
劣势
- 高可用性不好,比如每30秒写一次数据,那么就有可能丢掉一部分数据
- 才用fork方式,由子进程存储数据,如果数据集过大可能会导致整个服务停止几百毫秒甚至是1秒
配置
# 打开配置文件
$ vim redis.conf
# 配置持久化频率
save 900 1 # 每900秒至少有1个key发生变化就持久化1次
save 300 10 # 每300秒至少有10个key发生变化就持久化1次
save 60 10000 # 每60秒至少有10000个key发生变化就持久化1次
# 配置存储文件名
dbfilename dump.rdb
# 配置保存的路径
dir ./
AOF
以日志的形式记录服务器的每一个操作。
优势
- 更高的数据安全性,可以配置修改就同步
- 拥有记录了所有操作的日志文件
劣势
- 文件大
- 同步效率低
配置
# 打开配置文件
$ vim redis.conf
# 开启
appendonly no 改为 appendonly yes
# 配置存储文件名
appendfilename "appendonly.aof"
# 配置同步策略
# appendfsync always 修改就同步
appendfsync everysec 每秒同步
# appendfsync no 不同步
# 清空数据库
flushall
# 查看数据库大小
dbsize
redis-benchmark
Redis自带的性能测试工具
$ src/redis-benchmark
$ src/redis-benchmark [-h <host>] [-p <port>] [-c <clients>] [-n <requests>] [-k <boolean>]
-h <hostname> Server hostname (default 127.0.0.1)
-p <port> Server port (default 6379)
-s <socket> Server socket (overrides host and port)
-a <password> Password for Redis Auth
-c <clients> Number of parallel connections (default 50)
-n <requests> Total number of requests (default 100000)
-d <size> Data size of SET/GET value in bytes (default 3)
--dbnum <db> SELECT the specified db number (default 0)
-k <boolean> 1=keep alive 0=reconnect (default 1)
-r <keyspacelen> Use random keys for SET/GET/INCR, random values
for SADD Using this option the benchmark will
expand the string __rand_int__ inside an argument
with a 12 digits number in the specified range from
0 to keyspacelen-1. The substitution changes every
time a command is executed. Default tests use this
to hit random keys in the specified range.
-P <numreq> Pipeline <numreq> requests. Default 1 (no pipeline).
-e If server replies with errors, show them on stdout.
(no more than 1 error per second is displayed)
-q Quiet. Just show query/sec values
--csv Output in CSV format
-l Loop. Run the tests forever
-t <tests> Only run the comma separated list of tests. The test
names are the same as the ones produced as output.
-I Idle mode. Just open N idle connections and wait.
Examples:
Run the benchmark with the default configuration against 127.0.0.1:6379:
$ redis-benchmark
Use 20 parallel clients, for a total of 100k requests, against 192.168.1.1:
$ redis-benchmark -h 192.168.1.1 -p 6379 -n 100000 -c 20
Fill 127.0.0.1:6379 with about 1 million keys only using the SET test:
$ redis-benchmark -t set -n 1000000 -r 100000000
Benchmark 127.0.0.1:6379 for a few commands producing CSV output:
$ redis-benchmark -t ping,set,get -n 100000 --csv
Benchmark a specific command line:
$ redis-benchmark -r 10000 -n 10000 eval 'return redis.call("ping")' 0
Fill a list with 10000 random elements:
$ redis-benchmark -r 10000 -n 10000 lpush mylist __rand_int__
On user specified command lines __rand_int__ is replaced with a random integer with a range of values selected by the -r option.
Nodejs 操作 Redis
官网上提供了各种语言访问 redis 的方法,大家可以看 https://redis.io/[clients](https://redis.io/clients) ,这里我们使用 nodejs 来连接 redis。官方推荐使用的是 node_redis
首先,我们来安装 nodejs 的 redis 包:
$ npm install redis
安装成功之后就可以进行redis库的连接了,创建连接的方法有下面几种:
// 连接本地默认端口且无密码redis
const redis = require('redis');
const client = redis.createClient();
// 连接远程无密码redis
const redis = require('redis');
const client = redis.createClient(6379, '10.211.55.12');
// 如果redis开启了密码认证
const redis = require('redis');
const client = redis.createClient(6379, '10.211.55.12');
client.auth('password', function(err, reply) {
console.log(reply);
});