zoukankan      html  css  js  c++  java
  • Redis NoSQL

    目录

    参考文档

    https://www.runoob.com/redis/redis-tutorial.html
    https://www.cnblogs.com/zhaohuhu/p/9140673.html

    Redis

    Redis(Remote DIctionary Server)是由 Salvatore Sanfilippo 开发的 NoSQL 存储系统。使用 ANSI C 语言编写,遵守 BSD 开源协议,是一个支持基于内存、网络的可持久化的日志型、Key-Value 数据库,并提供多种语言的 API。

    Redis 通常被称为数据结构服务器,因为其存储的 Value 可以是 String、Hash、List、Sets、Sorted Sets 等类型。

    MAC pro 上部署 Redis

    安装

     brew info redis
     brew install redis
    

    启动

     brew services start redis
    

    这个命令会在后台启动 Redis 服务,并且每一次登录系统,都会自动重启。假如你不希望自动启动服务,可以使用配置文件手动启动:

    redis-server /usr/local/etc/redis.conf
    

    Redis Client

    连接到 Redis

    # 没有身份认证时
    redis-cli -p 6379 -h 127.0.0.1
    
    # 有身份认证时
    redis-cli -p 6379 -h 127.0.0.1 -a yourpassword
    

    查看配置

    127.0.0.1:6379> CONFIG GET loglevel
    1) "loglevel"
    2) "notice"
    
    127.0.0.1:6379> CONFIG GET *
      1) "dbfilename"
      2) "dump.rdb"
      3) "requirepass"
      4) ""
      5) "masterauth"
      6) ""
      7) "cluster-announce-ip"
      8) ""
      9) "unixsocket"
     10) ""
     ...
    

    编辑配置

    redis 127.0.0.1:6379> CONFIG SET loglevel "notice"
    OK
    
    redis 127.0.0.1:6379> CONFIG GET loglevel
    1) "loglevel"
    2) "notice"
    

    设置密码(默认为空)

    127.0.0.1:6379> config get requirepass
    1) "requirepass"
    2) ""
    
    127.0.0.1:6379> config set requirepass fanguiju
    OK
    
    127.0.0.1:6379> config get requirepass
    (error) NOAUTH Authentication required.
    
    127.0.0.1:6379> auth fanguiju
    OK
    
    127.0.0.1:6379> config get requirepass
    1) "requirepass"
    2) "fanguiju"
    

    数据持久化

    Redis 提供了良好的数据持久化策略,保证内存中的数据不被丢失,在 Redis 服务器重启后,依然可以获取其中的数据。但大量的数据持久化必然涉及到内存的整理和消耗,所以应该根据应用的实际情况来进行选择。

    Redis 启动时,会先扫描数据持久化文件,将数据恢复到内存中。之后再根据持久化的规则运行。默认的条件下采用RDB模式进行数据备份,效率是最高的。如果开启了AOF模式则使用AOF持久化方式,这时RDB模式将不生效。

    RDB 模式

    RDB 是默认的持久化策略,为定期持久化,所以可能会导致数据的丢失。在对数据完整性要求不高的常客中可以使用 RDB 模式,因为其效率更高。

    在 redis.conf 中的持久化配置:

    save 900 1
    save 300 10
    save 60 10000
    
    
    rdbcompression yes
    rdbchecksum yes
    
    dbfilename dump.rdb
    dir /usr/local/var/db/redis/
    

    RDB 模式下,主动触发持久化的命令:

    1. 立即持久化 save 命令,会将全部的进程先挂起,直到 save 命令执行完成后,后续的进程才能执行,也就是会造成线程的阻塞;
    2. 后台持久化 bgsave 指令,不会马上数据备份,所以不会造成线程阻塞。

    AOF 模式

    AOF 模式可以实现实时的数据持久化,如果对数据的安全性要求较高,则应该使用 AOF 模式,但该模式的性能较低。

    开启 AOF 配置:

    appendonly yes
    
    appendfilename "appendonly.aof"
    appendfsync everysec
    no-appendfsync-on-rewrite no
    auto-aof-rewrite-percentage 100
    auto-aof-rewrite-min-size 64mb
    aof-load-truncated yes
    aof-use-rdb-preamble yes
    

    其中,appendfsync 定义了持久化策略,默认每秒备份一次,若采用 always 则实时备份,效率最低。

    数据类型

    String

    在这里插入图片描述
    Redis String 是最基本的数据类型,一个 Key 对应一个 Value,最大能存储 512MB。

    String 类型是二进制安全的,即 Redis 的 String 可以包含任何数据。比如 .jpg 文件或者序列化的对象。

    127.0.0.1:6379> set test_str "just test"
    OK
    
    127.0.0.1:6379> get test_str
    "just test"
    
    127.0.0.1:6379> del test_str
    (integer) 1
    

    List

    在这里插入图片描述
    Redis List 数据类型是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。List 最多可储存 2**32 - 1 个元素,即 4294967295,40 多亿个元素。

    127.0.0.1:6379> lpush test_list one
    (integer) 1
    127.0.0.1:6379> lpush test_list two
    (integer) 2
    127.0.0.1:6379> lpush test_list three
    (integer) 3
    
    127.0.0.1:6379> lrange test_list 0 1
    1) "three"
    2) "two"
    127.0.0.1:6379> lrange test_list 0 2
    1) "three"
    2) "two"
    3) "one"
    
    127.0.0.1:6379> del test_list
    (integer) 1
    

    Hash

    在这里插入图片描述
    Redis Hash 数据类型是一个基于 String 类型的 Key/Value 映射表,类似 Python 的字典数据类型,特别适合用于储存对象。

    127.0.0.1:6379> hmset test_hash key1 "v1" key2 "v2"
    OK
    
    127.0.0.1:6379> hget test_hash key1
    "v1"
    127.0.0.1:6379> hget test_hash key2
    "v2"
    
    127.0.0.1:6379> del test_hash
    (integer) 1
    

    Set

    Redis Set 数据类型是 String 类型的无序集合,集合是不会存在重复 Value 的。每个 Set 同样可以储存 40 多亿个成员。

    Set 是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。

    127.0.0.1:6379> sadd test_set one
    (integer) 1
    127.0.0.1:6379> sadd test_set one
    (integer) 0
    
    127.0.0.1:6379> sadd test_set two
    (integer) 1
    
    127.0.0.1:6379> smembers test_set
    1) "one"
    2) "two"
    
    127.0.0.1:6379> del test_set
    (integer) 1
    

    Sorted Set(ZSet)

    Redis ZSet 和 Set 的区别在于前者是有序的,每个元素都会关联一个 Double 类型的分数(Score),通过分数来为 ZSet 中的成员进行从小到大的排序。命令格式:zadd key score member

    127.0.0.1:6379> zadd test_zset 3 one
    (integer) 1
    127.0.0.1:6379> zadd test_zset 2 two
    (integer) 1
    127.0.0.1:6379> zadd test_zset 1 three
    (integer) 1
    
    127.0.0.1:6379> ZRANGEBYSCORE test_zset 0 1
    1) "three"
    127.0.0.1:6379> ZRANGEBYSCORE test_zset 0 2
    1) "three"
    2) "two"
    127.0.0.1:6379> ZRANGEBYSCORE test_zset 0 3
    1) "three"
    2) "two"
    3) "one"
    
    127.0.0.1:6379> del test_zset
    (integer) 1
    

    Python Redis

    >>> import redis
    >>> r = redis.Redis(host='localhost', port=6379, db=0)
    >>> r.set('foo', 'bar')
    True
    >>> r.get('foo')
    'bar'
    

    连接池

    redis-py 使用 Connection Pool 来管理实例对象对 Redis Server 的所有连接,避免多个实例对象多次建立、释放连接的开销。可以直接建立一个连接池,然后作为参数建立 Redis 实例对象,这样就可以实现多个实例共享一个连接池。

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
     
    import redis
     
    pool = redis.ConnectionPool(host='192.168.18.11', port=6379)
     
    r = redis.Redis(connection_pool=pool)
    r.set('foo', 'Bar')
    print r.get('foo')
    

    管道

    redis-py 默认执行每次请求都会创建(连接池申请连接)和断开(归还连接池)一次连接操作,如果想要在一次请求中执行多个命令,则可以使用 Pipline 实现一次请求执行多个命令,并且默认的,一次 Pipline 是原子性操作。

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
     
    import redis
     
    pool = redis.ConnectionPool(host='10.211.55.4', port=6379)
     
    r = redis.Redis(connection_pool=pool)
     
    # pipe = r.pipeline(transaction=False)
    pipe = r.pipeline(transaction=True)
    pipe.multi()
    pipe.set('name', 'alex')
    pipe.set('role', 'sb')
     
    pipe.execute()
    

    String 操作

    • 创建值:(默认)不存在则创建,存在则修改。
    set(name, value, ex=None, px=None, nx=False, xx=False)
    
         ex,过期时间(秒)
         px,过期时间(毫秒)
         nx,如果设置为True,则只有name不存在时,当前set操作才执行
         xx,如果设置为True,则只有name存在时,岗前set操作才执行
    
    • 批量创建
    mset(*args, **kwargs)
    
    # e.g.
    mset(k1='v1', k2='v2')
    mset({'k1': 'v1', 'k2': 'v2'})
    
    • 获取值
    get(name)
    
    • 批量获取
    mget(keys, *args)
    
    # e.g.
    mget('ylr', 'zhaogongzi')
    mget(['ylr', 'zhaogongzi'])
    
    • 获取字符串长度
    strlen(name)
    
    • 追加:在后面追加内容
    append(name, value)
    
    • 获取子序列(切片)
    getrange(name, start, end)
    
    • 修改子序列:修改字符串内容,从指定字符串索引开始向后替换,新值太长时,则向后添加。
    setrange(name, offset, value)
    
    • 创建新值并获取原来的值
    getset(name, value)
    
    • 值自增(整型):自增 name 对应的值,当 name 不存在时,则创建 name=amount,否则,则自增。
    incr(self, name, amount=1)
    
    • 值自增(浮点型):自增 name 对应的值,当 name 不存在时,则创建 name=amount,否则,则自增。
    incrbyfloat(self, name, amount=1.0)
    
    • 自减
    decr(self, name, amount=1)
    

    List 操作

    • 创建 List 实例,并添加元素
    # 每个新的元素都添加到列表的最左边
    lpush(name, values)
    
    # 每个新的元素都添加到列表的最右边
    rpush(name, values)
    
    • 向已存在的 List 实例添加元素
    lpushx(name, value)
    rpushx(name, value) 
    
    • 查看元素的个数
    llen(name)
    
    • 插入元素:在某一个值前或后插入一个新值
    linsert(name, where, refvalue, value))
    
    • 获取某个 index 的值
    lindex(name, index)
    
    • 修改某个 index 的值
    r.lset(name, index, value)
    
    • 删除指定元素
    r.lrem(name, value, num)
    
    • 弹出
    lpop(name)
    rpop(name)
    
    • 切片
    lrange(name, start, end)
    
    • 排他:移除没有在 [start, end] 索引之间的值
    ltrim(name, start, end)
    

    Hash 操作

    • 创建并添加元素
    hset(name, key, value)
    
    • 批量添加
    hmset(name, mapping)
    
    # e.g.
    hmset('xx', {'k1':'v1', 'k2': 'v2'})
    
    • 获取 key 映射的 value
    hget(name,key)
    
    • 批量获取
    
    mget('xx', ['k1', 'k2'])
    hmget('xx', 'k1', 'k2')
    
    • 获取所有键值对
    hgetall(name)
    
    • 获取键值对的个数
    hlen(name)
    
    • 获取所有 keys
    hkeys(name)
    
    • 获取所有 values
    hvals(name)
    
    • 检查 key 是否存在
    hexists(name, key)
    
    • 删除指定的键值对
    hdel(name, *keys)
    
    • 自增(整型):不存在则创建 key=amount
    hincrby(name, key, amount=1)
    
    • 自增(浮点型)
    hincrbyfloat(name, key, amount=1.0)
    

    Set 操作

    • 创建并添加元素
    sadd(name,values)
    
    • 获取集合中元素的个数
    scard(name)
    
    • 差集:在第一个 name 对应的集合中且不在其他 name 对应的集合的元素集合
    sdiff(keys, *args)
    
    • 导出差集:获取第一个 name 对应的集合中且不在其他 name 对应的集合,再将其新加入到 dest 对应的集合中
    sdiffstore(dest, keys, *args)
    
    • 并集:获取多个 name 对应集合的并集
    sinter(keys, *args)
    
    • 导出并集:获取多个 name 对应集合的并集,再讲其加入到 dest 对应的集合中
    sinterstore(dest, keys, *args)
    
    • 检查成员是否存在
    sismember(name, value)
    
    • 获取所有成员
    smembers(name)
    
    • 移动成员
    smove(src, dst, value)
    
    • 弹出成员
    spop(name)
    
    • 随机获取若干个成员
    srandmember(name, numbers)
    
    • 删除指定成员
    srem(name, values)
    
    • 交集
    sunion(keys, *args)
    
    • 导出交集
    sunionstore(dest,keys, *args)
    

    ZSet 操作

    对于有序集合,每一个元素有两个值,即:值和分数,分数专门用来做排序。

    • 创建并添加有序集合
    zadd(name, *args, **kwargs)
    
    # e.g.
    zadd('zz', 'n1', 1, 'n2', 2)
    zadd('zz', n1=1, n2=2)
    
    • 获取指定成员数量
    zcard(name)
    
    • 获取有序集合中分数在 [min,max] 之间的成员个数
    zcount(name, min, max)
    
    • 删除指定成员
    zrem(name, values)
    
    • 根据分数范围删除
    zremrangebyscore(name, min, max)
    
    • 根据排行范围删除
    zremrangebyrank(name, min, max)
    
    • 查看成员的分数
    zscore(name, value)
    

    常规操作

    • 删除
    delete(*names)
    
    • 判断是否存在
    exists(name)
    
    • 重命名
    rename(src, dst)
    
    • 将对象移动到指定的 DB
    move(name, db))
    
    • 判断对象类型
    type(name)
    
  • 相关阅读:
    Erlang 杂记 IV
    ASP.NET MVC的View是如何被呈现出来的?[设计篇]
    面向对象—在线文件管理模块
    软件开发中个人在团队里的效绩评定
    用go语言遍历文件夹
    磁盘缓存的算法:写算法
    一种Lua到C的封装
    从信息系统界面设计引发的思考
    基于Backbone.js的JavaScript MVC示例程序
    C和C++
  • 原文地址:https://www.cnblogs.com/jmilkfan-fanguiju/p/12789742.html
Copyright © 2011-2022 走看看