-
Redis介绍
-
特点及优点
1、开源的,使用C编写,基于内存且支持持久化 2、高性能的Key-Value的NoSQL数据库 3、支持数据类型丰富,字符串strings,散列hashes,列表lists,集合sets,有序集合sorted sets 等等 4、支持多种编程语言(C C++ Python Java PHP ... )
-
与其他数据库对比
1、MySQL : 关系型数据库,表格,基于磁盘,慢 2、MongoDB:键值对文档型数据库,值为JSON文档,基于磁盘,慢,存储数据类型单一 3、Redis的诞生是为了解决什么问题?? 解决硬盘IO带来的性能瓶颈
-
应用场景
1、使用Redis来缓存一些经常被用到、或者需要耗费大量资源的内容,通过这些内容放到redis里面,程序可以快速读取这些内容 2、一个网站,如果某个页面经常会被访问到,或者创建页面时消耗的资源比较多,比如需要多次访问数据库、生成时间比较长等, 我们可以使用redis将这个页面缓存起来,减轻网站负担,降低网站的延迟,比如说网站首页等 3、比如新浪微博 # 新浪微博,基于TB级的内存数据库 # 内容 :存储在MySQL数据库 # 关系 :存储在redis数据库 # 数字 :粉丝数量,关注数量,存储在redis数据库 # 消息队列
-
DB-Engines 数据库流行度排行榜2019年11月最新排名
-
redis 版本
1、最新版本:5.0 2、常用版本:2.4、2.6、2.8 3.0(里程碑)、3.2、3.4、4.0、5.0 3、图形界面管理工具(写的一般) RedisDesktopManager # 为了解决负载问题,所以发明了redis
-
诞生历程
# 1、历史 LLOOGG.com 帮助别的网站统计用户信息,各个网站发送的浏览记录都会存储到存储队列,5-10000条记录,多余5条需要收费 # 2、原理 FIFO机制,先进先出,满了进一条就出一条,网站越多,队列越多,推入和弹出操作越多 # 3、技术及问题 开始使用MySQL进行硬盘读写,速度很慢,导致无法实时显示,所以自己写了一个列表结构的内存数据库,程序性能不会受到硬盘IO的限制,加了持久化的功能 # 4、redis数据库戛然而生
-
redis 附加功能
1、持久化 将内存中数据保存到磁盘中,保证数据安全,方便进行数据备份和恢复 2、发布与订阅功能 将消息同时分发给多个客户端,用于构建广播系统 3、过期键功能 为键设置一个过期时间,让它在指定时间内自动删除 <节省内存空间> # 音乐播放器,日播放排名,过期自动删除 4、事务功能 原子的执行多个操作 5、主从复制 6、Sentinel哨兵
-
-
Redis安装
-
Ubuntu
# 安装 sudo apt-get install redis-server # 服务端启动 sudo /etc/init.d/redis-server start | stop | restart | status # 客户端连接 redis-cli -h IP地址 -p 6379 -a 密码 redis-cli 127.0.0.1:6379>ping PONG
-
Windows
1、下载安装包 https://github.com/ServiceStack/redis-windows/blob/master/downloads/redis-64.3.0.503.zip 2、解压 3、启动服务端 双击解压后的 redis-server.exe 4、客户端连接 双击解压后的 redis-cli.exe # 问题:关闭终端后服务终止 # 解决:将Redis服务安装到本地服务 1、重命名 redis.windows.conf 为 redis.conf,作为redis服务的配置文件 2、cmd命令行,进入到redis-server.exe所在目录 3、执行:redis-server --service-install redis.conf --loglevel verbose 4、计算机-管理-服务-Redis-启动 # 卸载 到 redis-server.exe 所在路径执行: 1、redis-server --service-uninstall 2、sc delete Redis
-
-
配置文件详情
-
配置文件所在路径
1、Ubuntu /etc/redis/redis.conf 2、windows 下载解压后的redis文件夹中 redis.windows.conf redis.conf
-
设置连接密码
1、requirepass 密码(500行) 2、重启服务 sudo /etc/init.d/redis-server restart 3、客户端连接 redis-cli -h 127.0.0.1 -p 6379 -a 123456 127.0.0.1:6379>ping
-
允许远程连接
1、注释掉本地IP地址绑定 69行: # bind 127.0.0.1 ::1 2、关闭保护模式(默认开启,把yes改为no) 88行: protected-mode no 3、重启服务 sudo /etc/init.d/redis-server restart
-
远程连接测试(Windows连接Ubuntu的Redis服务)
# cmd命令行 1、d: 2、cd Redis3.0 3、redis-cli -h x.x.x.x 4、x.x.x.x:6379>ping # RedisDesktopManage 连接,注意windows防火墙问题(关闭)
-
-
数据类型
-
字符串类型(string)
-
特点
字符串、数字、都会转化为字符串来存储
-
基本命令
1、set key value 2、setnx key value 3、set key value ex seconds 4、get key 5、mset key1 value1 key2 value2 6、mget key1 key2 key3 7、stren key # 数字操作 8、incr key 9、decr key
-
扩展命令
1、append key value 2、setrange key index value 3、getrange key start stop 4、incrby key step 5、decrby key step
-
常用命令
set | get命令 作用: 设置键值,获取键对应的值 命令格式: set key value get key set命令之 - setnx # 键不存在,进行设置,如果键已经存在,则不进行任何操作 setnx key value : 键不存在时才能进行设置(重要) set命令之 - ex 作用: 设置过期时间 命令格式: set key value ex seconds mset | mget mset key1 value1 key2 value2 key3 value3 ... ... mget key1 key2 key3 ... ... 作用: 同时设置多个值,获取多个值
-
键命名规范
利用层级关系 mset dayin:email [email protected] dy:email [email protected]
-
strlen命令
作用: 获取值的长度 命令格式: strlen key 127.0.0.1:6379> strlen name (integer) 11 127.0.0.1:6379>
-
字符串索引操作
setrange key 索引值 value 作用: 从索引值开始,value替换原内容 127.0.0.1:6379> get message "hello world" 127.0.0.1:6379> setrange message 6 'dayin' (integer) 12 127.0.0.1:6379> get message "hello dayin" 127.0.0.1:6379> getrange key 起始值 终止值 作用: 获取指定范围切片内容 127.0.0.1:6379> get message "hello dayin" 127.0.0.1:6379> getrange message 0 4 "hello" 127.0.0.1:6379> getrange message 0 -1 "hello dayin"
-
append key value
作用: 追加拼接value的值 127.0.0.1:6379> set message 'hello ' OK 127.0.0.1:6379> append message 'world' (integer) 11 127.0.0.1:6379> get message "hello world" 127.0.0.1:6379>
-
整数操作
INCRBY key 步长 DECRBY key 步长 NCR key : +1操作 DECR key : -1操作 应用场景: 微博粉丝增加或减少就可以使用
-
浮点数操作
incrbyfloat key increment
-
string 命令汇总
# 字符串操作 1、set key value 2、setnx key value 3、get key 3、mset key1 value1 key2 value2 key3 value3 4、mget key1 key2 ke y3 5、set key value ex seconds 6、strlen key # 数字操作 7、incrby key 步长 8、decrby key 步长 9、incr key 10、decr key 11、incrbyfloat key number # 设置过期时间的两种方式 # 方式一 1、set key value ex 3 # 方式二 1、set key value 2、expire key 5 # 秒 3、pexpire key 5 # 毫秒 # 查看存活时间 ttl key # 删除过期 persist key
-
通用命令汇总
# 切换库 select number(0-15) # 查看所有键 keys * # 键类型 TYPE key # 键是否存在 exists key # 删除键 del key # 键重命名 rename key newkey # 返回旧值并设置新值(如果键不存在,就创建并赋值) getset key value # 清除当前库中所有数据(慎用) flushdb # 清除所有库中所有数据(慎用) flushall
-
string 数据类型注意
# key值取值原则 1、key值不宜过长,消耗内存,且在数据中查找这类键值的计算成本高 2、不宜过短,可读性较差 # 值 1、一个字符串类型的值最多能存储512M内容
-
-
列表数据类型
-
特点
1、元素是字符串类型 2、列表头尾增删快,中间增删慢,增删元素是常态 3、元素可重复 4、最多可包含2^32 -1个元素 5、索引同python列表
-
头尾压入元素(LPUSH | RPUSH)
# LPUSH : Left # RPUSH : Right ['lucy','tom','10']
-
查看|设置 列表元素
查看(LRANGE) # lrange key start stop lrange mylist1 0 2 # 显示前3个元素 lrange mylist1 0 -1 # 显示列表中所有元素 获取指定位置元素(LINDEX) lindex key index 设置指定位置元素的值(LSET) lset key index value 获取列表长度(LLEN) llen key
-
头尾弹出元素(LPOP | RPOP)
LPOP key : 从列表头部弹出一个元素 RPOP key : 从列表尾部弹出一个元素 RPOPLPUSH source destination : 从一个列表尾部弹出元素压入到另一个列表头部 rpoplpush mylist1 mylist2
-
移除指定元素(LREM)
LREM key count value count>0:表示从头部开始向表尾搜索,移除与value相等的元素,数量为count count<0:表示从尾部开始向表头搜索,移除与value相等的元素,数量为count count=0:移除表中所有与value相等的值 示例: lrem mylist 0 tom lrem mylist 1 tom lrem mylist -2 tom
-
去除指定范围外元素(LTRIM)
LTRIM key start stop 应用场景: 保存微博评论最后500条 weibo:comments [评论,评论,。。。。。,。。。。] # LPUSH (考虑列表中元素顺序) LTRIM weibo:comments 0 499 # RPUSH LRTIM weibo:comments -500 -1
-
列表中插入值(LINSERT)(了解)
LINSERT key BEFORE|AFTER value new_value key和pivot不存在,不进行任何操作 示例代码 [1 2 3 4 5 2 ] LINSERT mylist after 2 8
-
阻塞弹出(BLPOP | BRPOP)(重要)
BLPOP key timeout BRPOP key timeout 1、如果弹出的列表不存在或者为空,就会阻塞 2、超时时间设置为0,就是永久阻塞,直到有数据可以弹出 3、如果多个客户端阻塞再同一个列表上,使用First In First Service原则,先到先服务 示例: brpop mylist 0 # 永久阻塞 brpop mylist 3 # 超时时间3秒
-
列表常用命令总结
# 增 1、LPUSH key value1 value2 2、RPUSH key value1 value2 3、RPOPLPUSH source destination 4、LINSERT key after|before value newvalue # 查 5、LRANGE key start stop 6、LLEN key # 删 7、LPOP key 8、RPOP key 9、BLPOP key timeout 10、BRPOP key timeout 11、LREM key count value 12、LTRIM key start stop # 微博评论500条 # 改 13、LSET key index newvalue
-
-
位图操作
-
定义
1、位图不是真正的数据类型,它是定义在字符串类型中 2、一个字符串类型的值最多能存储512M字节的内容,位上限:2^32 # 1MB = 1024KB # 1KB = 1024Byte(字节) # 1Byte = 8bit(位)
-
强势点
可以实时的进行统计,极其节省空间。官方在模拟1亿2千8百万用户的模拟环境下, 在一台MacBookPro上,典型的统计如“日用户数”的时间消耗小于50ms, 占用16MB内存
-
常用命令
# 设置某一位上的值(offset是偏移量,从0开始) setbit key offset value # 获取某一位上的值 GETBIT key offset # 统计键所对应的值中有多少个 1 BITCOUNT key
-
应用场景案例
网站用户的上线次数统计(寻找活跃用户) 用户名为key,上线的天作为offset,上线设置为1 示例: 用户名为 user001 的用户,今年第1天上线,第30天上线 SETBIT user001 0 1 SETBIT user001 29 1 BITCOUNT user001
-
-
Hash散列数据类型
-
定义
1、由field和关联的value组成的键值对 2、field和value是字符串类型 3、一个hash中最多包含2^32-1个键值对
-
优点
1、节约内存空间 2、每创建一个键,它都会为这个键储存一些附加的管理信息(比如这个键的类型,这个键最后一次被访问的时间等) 3、键越多,redis数据库在储存附件管理信息方面耗费内存越多,花在管理数据库键上的CPU也会越多
-
缺点(不适合hash情况)
1、使用二进制位操作命令:SETBIT、GETBIT、BITCOUNT等,如果想使用这些操作,只能用字符串键 2、使用过期键功能:键过期功能只能对键进行过期操作,而不能对散列的字段进行过期操作
-
基本命令操作
# 1、设置单个字段 HSET key field value HSETNX key field value # 2、设置多个字段 HMSET key field value field value # 3、返回字段field个数 HLEN key # 4、判断字段是否存在(不存在返回0) HEXISTS key field # 5、返回字段值 HGET key field # 6、返回多个字段值 HMGET key field filed # 7、返回所有的键值对 HGETALL key # 8、返回所有字段名 HKEYS key # 9、返回所有值 HVALS key # 10、删除指定字段 HDEL key field field field # 11、在字段对应值上进行整数增量运算 HINCRBY key field increment # 12、在字段对应值上进行浮点数增量运算 HINCRBYFLOAT key field increment
-
应用场景:微博好友关注
1、用户ID为key,Field为好友ID,Value为关注时间 key field value user:10000 user:606 20190520 user:605 20190521 2、用户维度统计 统计数包括:关注数、粉丝数、喜欢商品数、发帖数 用户为key,不同维度为field,value为统计数 比如关注了5人 HSET user:10000 fans 5 HINCRBY user:10000 fans 1
-
-
集合数据类型(set)
-
特点
1、无序、去重 2、元素是字符串类型 3、最多包含2^32-1个元素
-
基本命令
# 1、增加一个或者多个元素,自动去重 SADD key member1 member2 # 2、查看集合中所有元素 SMEMBERS key # 3、删除一个或者多个元素,元素不存在自动忽略 SREM key member1 member2 # 3、随机弹出元素(默认弹出一个) SPOP key [count] # 4、元素是否存在 SISMEMBER key member # 5、随机返回集合中指定个数的元素,默认为1个 SRANDOMMEMBER key [count] # 6、返回集合中元素的个数,不会遍历整个集合,只是存储在键当中了 SCARD key # 7、把元素从源集合移动到目标集合 SMOVE source destination member # 8、差集(number1 1 2 3 number2 1 2 4) SDIFF key1 key2 # 9、差集保存到另一个集合中 SDIFFSTORE destination key1 key2 # 10、交集 SINTER key1 key2 SINTERSTORE destination key1 key2 # 11、并集 SUNION key1 key2 SUNIONSTORE destination key1 key2
-
应用场景: 新浪微博的共同关注
需求: 当用户访问另一个用户的时候,会显示出两个用户共同关注过哪些相同的用户 设计: 将每个用户关注的用户放在集合中,求交集即可 实现: user001 = {'peiqi','qiaozhi','danni'} user002 = {'peiqi','qiaozhi','lingyang'} user001和user002的共同关注为: # SINTERSTORE user_all user001 user002 # SINTER user001 user002
-
-
有序集合 sortedset
-
特点
1、有序、去重 2、元素是字符串类型 3、每个元素都关联着一个浮点数分值(score),并按照分值从小到大的顺序排列集合中的元素(分值可以相同) 4、最多包含2^32-1元素
-
示例
-
一个保存了水果价格的有序集合
-
一个保存了员工薪水的有序集合
-
-
增加
zadd key score member # 在有序集合中添加一个成员 zadd key score member # 查看指定区间元素(升序) zrange key start stop [withscores] # 查看指定区间元素(降序) ZREVRANGE key start stop [withscores] # 查看指定元素的分值 ZSCORE key member # 返回指定区间元素 # offset : 跳过多少个元素 # count : 返回几个 # 小括号 : 开区间 zrangebyscore salary (6000 (8000 zrangebyscore key min max [withscores] [limit offset count] limit 2 3 # 显示第 3 4 5 三个元素 # 删除成员 zrem key member # 增加或者减少分值 zincrby key increment member # 返回元素排名 zrank key member # 返回元素逆序排名 zrevrank key member # 删除指定区间内的元素 zremrangebyscore key min max # 返回集合中元素个数 zcard key # 返回指定范围中元素的个数 zcount key min max zcount fruits 4 7 zcount fruits (4 7 # 并集 zunionstore destination numkeys key [weights 权重值] [AGGREGATE SUM|MIN|MAX] # zunionstore zset4 2 zset1 zset2 aggregate max # 交集:和并集类似,只取相同的元素 ZINTERSTORE destination numkeys key1 key2 WEIGHTS weight AGGREGATE SUM|MIN|MAX
-
应用场景1:网易云音乐排行榜
1、每首歌的歌名作为元素(先不考虑重复) 2、每首歌的播放次数作为分值 3、使用ZREVRANGE来获取播放次数最多的歌曲
-
应用场景2: 京东商品畅销榜
# 第1天 ZADD mobile-001 5000 'huawei' 4000 'oppo' 3000 'iphone' # 第2天 ZADD mobile-002 5200 'huawei' 4300 'oppo' 3230 'iphone' # 第3天 ZADD mobile-003 5500 'huawei' 4660 'oppo' 3580 'iphone' 问题:如何获取三款手机的销量排名? # 1、ZADD mobile-003 5500 'huawei' 4660 'oppo' 3580 'iphone' 2、ZUNIONSTORE mobile-001:003 mobile-001 mobile-002 mobile-003 AGGREGATE MAX
-
-
-
与Python交互
-
模块
-
Ubuntu
sudo pip3 install redis
-
Windows
python -m pip install redis
-
使用流程
import redis # 创建数据库连接对象 r = redis.Redis(host='127.0.0.1',port=6379,db=0,password='123456')
-
Python操作字符串类型
import redis r = redis.Redis(host='192.168.43.49',port=6379,password='123456',db=0) r.set('mystring','python') # b'python' print(r.get('mystring')) # False print(r.setnx('mystring','socket')) # mset:参数为字典 r.mset({ 'mystring2':'mysql','mystring3':'mongodb'}) # mget:结果为一个列表 print(r.mget('mystring','mystring2','mystring3')) # mystring长度:6 print(r.strlen('mystring')) # 数字类型操作 r.set('number',10) r.incrby('number',5) r.decrby('number',5) r.incr('number') r.decr('number') r.incrbyfloat('number',6.66) r.incrbyfloat('number',-6.66) # b'10' print(r.get('number'))
-
案例1:网易音乐排行榜(有序集合)
import redis r = redis.Redis(host='192.168.43.49',port=6379,password='123456',db=0) r.zadd('ranking',{ 'song1':1,'song2':1,'song3':1,'song4':1}) r.zadd('ranking',{ 'song5':1,'song6':1,'song7':1}) r.zadd('ranking',{ 'song8':1,'song9':1}) r.zincrby('ranking',50,'song3') r.zincrby('ranking',60,'song5') r.zincrby('ranking',80,'song7') # 获取前10名 rlist = r.zrevrange('ranking',0,2,withscores=True) i = 1 for r in rlist: print('第%d名:%s' % (i,r[0].decode())) i += 1
-
案例2: 京东商品畅销榜
import redis r = redis.Redis(host='192.168.43.49',port=6379,password='123456',db=0) # 第1天 day01_dict = { 'huawei' : 5000, 'oppo' : 4000, 'iphone' : 3000 } # 第2天 day02_dict = { 'huawei' : 5200, 'oppo' : 4300, 'iphone' : 3230 } # 第3天 day03_dict = { 'huawei' : 5500, 'oppo' : 4660, 'iphone' : 3580 } r.zadd('mobile-day01',day01_dict) r.zadd('mobile-day02',day02_dict) r.zadd('mobile-day03',day03_dict) r.zunionstore('mobile-day01:03',('mobile-day01','mobile-day02','mobile-day03'),aggregate='max') rlist = r.zrevrange('mobile-day01:03',0,-1,withscores=True) i = 1 for r in rlist: print('第{}名:{}'.format(i,r[0].decode()) )
-
-
end…