redis-快速开始(redis键值设计)

本文详细介绍了在Linux系统中安装Redis的过程,包括下载安装包、编译安装、配置环境变量、启动服务以及设置密码。此外,还提到了在Ubuntu 20.04上的安装方法。对于Redis的基础操作,如连接、命令行使用、Windows安装和图形化工具的使用也进行了讲解。在Spring Boot中集成Redis使用Lettuce和Jedis的区别和配置方法进行了对比。最后,分享了Redis键值设计的开发规范和管理技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、Linux下安装redis

1. linux下编译安装redis

第一步:下载安装包

官网:https://redis.io/

下载最新redis。

wget http://download.redis.io/releases/redis-5.0.7.tar.gz

第二步:编译安装

解压、编译
make test执行没有报错的话,就代表编译成功。

编译成功后,进入src文件夹,执行make install进行Redis安装

tar -zxvf redis-5.0.7.tar.gz 
cd redis-5.0.7/
make PREFIX=/usr/local/redis install   (/usr/local/redis为指定的安装目录)	

注意:如下 etc目录是我们自己创建的

mkdir /usr/local/redis/etc/
cp redis.conf /usr/local/redis/etc/
cd /usr/local/redis/bin/

安装完后会在/usr/local/redis下出现一个bin目录,bin目录中就是我们要使用的内容.

配置配置环境变量
vim /etc/profile
export PATH=“$PATH:/usr/local/redis/bin”
保存退出
让环境变量立即生效

source /etc/profile
过程问题总结
  1. 编译 报错 zmalloc.h:50:31: 致命错误:jemalloc/jemalloc.h:没有那个文件或目录

解决方案:添加编译选项 MALLOC=libc
执行命令:make MALLOC=libc
举例

make PREFIX=/usr/local/redis MALLOC=libc  install
  1. make test报错:You need tcl 8.5 or newer in order to run the Redis test
    解决方式
    安装tcl
yum list tcl
yum install -y tcl
  1. 编译报错:
  In file included from server.c:30:0:
  server.h:1045:5: error: expected specifier-qualifier-list before ‘_Atomic’
       _Atomic unsigned int lruclock; /* Clock for LRU eviction */
       ^
  server.c: In function ‘serverLogRaw’:
  server.c:1028:31: error: ‘struct redisServer’ has no member named ‘logfile’
       int log_to_stdout = server.logfile[0] == '\0';
                                 ^
  server.c:1031:23: error: ‘struct redisServer’ has no member named ‘verbosity’
       if (level < server.verbosity) return;
                         ^
  server.c:1033:47: error: ‘struct redisServer’ has no member named ‘logfile’
       fp = log_to_stdout ? stdout : fopen(server.logfile,"a");
                                                 ^
  server.c:1046:47: error: ‘struct redisServer’ has no member named ‘timezone’
           nolocks_localtime(&tm,tv.tv_sec,server.timezone,server.daylight_active);
                                                 ^
  server.c:1046:63: error: ‘struct redisServer’ has no member named ‘daylight_active’
           nolocks_localtime(&tm,tv.tv_sec,server.timezone,server.daylight_active);
                                                                 ^
  server.c:1049:19: error: ‘struct redisServer’ has no member named ‘sentinel_mode’
           if (server.sentinel_mode) {

运行gcc -v查看gcc版本,Redis要求gcc版本在5.3以上,运行以下命令可安装gcc:
升级gcc到5.3及以上,如下升级到gcc 9.3:

  yum -y install centos-release-scl
  yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils
  scl enable devtoolset-9 bash
  gcc --version

需要注意的是scl命令启用只是临时的,退出shell或重启就会恢复原系统gcc版本。

如果要长期使用gcc 9.3的话:

  echo "source /opt/rh/devtoolset-9/enable" >>/etc/profile

这样退出shell重新打开就是新版的gcc了,其他版本同理,修改devtoolset版本号即可。

【重要】总结

Redis要求gcc版本在5.3以上,参考上节临时升级gcc

第四步:编辑配置文件

准备配置文件,Redis服务在启动的时候可以指定配置文件,我们可以从redis的源码目录中拷贝一份配置文件模板到redis的安装目录

vim /usr/local/redis/etc/redis.conf
# 修改一下配置
# redis以守护进程的方式运行
# no表示不以守护进程的方式运行(会占用一个终端)  
daemonize yes

# 客户端闲置多长时间后断开连接,默认为0关闭此功能                                      
timeout 300

# 设置redis日志级别,默认级别:notice                    
loglevel verbose

# 设置日志文件的输出方式,如果以守护进程的方式运行redis 默认:"" 
# 并且日志输出设置为stdout,那么日志信息就输出到/dev/null里面去了 
logfile stdout
# 设置密码授权
requirepass <设置密码>
# 监听ip
bind 127.0.0.1 

注意:如果是阿里云、腾讯云
bind 0.0.0.0
protected-mode no

ps:
redis3.2版本后新增protected-mode配置,默认是yes,即开启。设置外部网络连接redis服务,设置方式如下:

1、关闭protected-mode模式,此时外部网络可以直接访问

2、开启protected-mode保护模式,需配置bind ip或者设置访问密码

第五步:启动redis服务

redis-server作为启动服务端的工具,redis-cli作为启动的客户端的工具

  • 前端模式启动
    运行./redis-server /usr/local/redis/etc/redis.conf (redis.conf为redis的配置文件,可自行指定位置)
    将以前端模式启动,前端模式启动的缺点是ssh命令窗口关闭则redis-server程序结束,线上不推荐使用此方法,出现如图则启动成功:

  • 后端模式启动服务端
    启动后自动在后台运行,与ssh窗口是否关闭无关(需要配置)

    修改redis.conf配置文件,vi redis.conf 找到daemonize no,修改为yes,即是用后端模式启动
    (不修改daemonize 也可,在前端模式启动命令后加&,./redis-server redis.conf & 也可实现窗口关闭,程序不会结束)

保存退出后,进行后端模式启动:

nohup redis-server /usr/local/redis/etc/redis.conf  > /dev/null 2>&1 &

然后查看是否成功启动服务:ps -ef|grep redis

第六步:redis设置密码

设置密码有两种方式。

  1. 命令行设置密码。
    运行cmd切换到redis根目录,先启动服务端
    另开一个cmd切换到redis根目录,启动客户端
>redis-cli.exe -h 127.0.0.1 -p 6379

客户端使用config get requirepass命令查看密码

>config set requirepass 123456
>OK

一旦设置密码,必须先验证通过密码,否则所有操作不可用

>config get requirepass
(error)NOAUTH Authentication required

使用auth password验证密码

>auth 123456
>OK
>config get requirepass
1)"requirepass"
2)"123456"

命令行设置的密码在服务重启后失效,所以一般不使用这种方式。

  1. 配置文件设置密码
    找到redis.conf配置文件

修改requirepass这个参数,如下配置:
修改redis.conf配置文件

#指定密码123456
requirepass 123

保存redis.conf后重启redis就可以了

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

2. Ubuntu20.04上安装Redis

安装Redis

sudo apt install redis-server
sudo systemctl status redis-server

二、配置和使用

配置Redis

sudo vim /etc/redis/redis.conf
sudo systemctl restart redis-server

默认情况下,Redis 不允许远程连接。你仅仅只能从127.0.0.1(localhost)连接 Redis 服务器 - Redis 服务器正在运行的机器上。

如果你正在使用单机,数据库也同样在这台机器上,你不需要启用远程访问。

# bind 0.0.0.0 ::1

使用下面的命令来验证 Redis 服务器正在监听端口6379:

ss -an | grep 6379

连接

redis-cli -h host -p port -a password

host:远程redis服务器host
port:远程redis服务端口

password:远程redis服务密码(无密码的的话就不需要-a参数了)

redis-cli -h 127.0.0.1 -p 6379

查看key

#获取 redis 中所有的 key 可用使用 *。
KEYS *
#查找以 w3c 为开头的 key
KEYS w3c*

三、windows下安装redis

redis 服务安装(新)

redis 安装(新)参考如下链接:

https://www.runoob.com/redis/redis-install.html
https://github.com/tporadowski/redis/releases

打开一个 cmd 窗口 使用 cd 命令切换目录到 C:\redis 运行:

redis-server.exe redis.windows.conf

Redis图形化工具——AnotherRedisDeskTopManager

Github地址为:https://github.com/qishibo/AnotherRedisDesktopManager

下载地址:https://github.com/qishibo/AnotherRedisDesktopManager/releases

四、spring boot 集成 redis lettuce(jedis)

Springboot2.0整合redis–Lettuce版本
参考URL:https://blog.csdn.net/qq_40102894/article/details/91894240
spring boot 集成 redis lettuce(jedis)
参考URL: https://www.cnblogs.com/achengmu/p/11345220.html
SpringBoot2集成redis,使用lettuce客户端
参考URL: https://cloud.tencent.com/developer/article/1425377

spring boot框架中已经集成了redis,在1.x.x的版本时默认使用的jedis客户端,现在是2.x.x版本默认使用的lettuce客户端,两种客户端的区别如下

# Jedis和Lettuce都是Redis Client

# Jedis 是直连模式,在多个线程间共享一个 Jedis 实例时是线程不安全的,
# 如果想要在多线程环境下使用 Jedis,需要使用连接池,
# 每个线程都去拿自己的 Jedis 实例,当连接数量增多时,物理连接成本就较高了。
# Lettuce的连接是基于Netty的,连接实例可以在多个线程间共享,
# 所以,一个多线程的应用可以使用同一个连接实例,而不用担心并发线程的数量。
# 当然这个也是可伸缩的设计,一个连接实例不够的情况也可以按需增加连接实例。

# 通过异步的方式可以让我们更好的利用系统资源,而不用浪费线程等待网络或磁盘I/O。
# Lettuce 是基于 netty 的,netty 是一个多线程、事件驱动的 I/O 框架,
# 所以 Lettuce 可以帮助我们充分利用异步的优势。

Lettuce和Jedis的都是连接Redis Server的客户端程序。Jedis在实现上是直连redis server,多线程环境下非线程安全,除非使用连接池,为每个Jedis实例增加物理连接。Lettuce基于Netty的连接实例(StatefulRedisConnection),可以在多个线程间并发访问,且线程安全,满足多线程环境下的并发访问,同时它是可伸缩的设计,一个连接实例不够的情况也可以按需增加连接实例

lettuce采用netty连接redis server,实例可以在多个线程间共享,不存在线程不安全的情况,这样可以减少线程数量。当然,在特殊情况下,lettuce也可以使用多个实例。有点类似于NIO的模式。

1. 使用步骤

Springboot集成redis大家都会用,主要就是使用RedisTemplate类来进行各种操作。

  1. maven引入
        <!--引入redis-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!-- redis依赖commons-pool 这个依赖一定要添加:创建连接池 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>
  1. 配置文件
    在这里插入图片描述如果你感觉并不需要这个pool,把pool的配置给去掉就行了:
    此时需要一个注意的地方,如果你配置了这个pool,那么必须在pom.xml添加上commons-pool2的依赖。没配置pool的话,可以不引用。

如果要在代码中使用RedisTemplate,那么配完上面的就已经可以用了,不过RedisTemplate默认只能支持RedisTemplate<String,String>形式的,也就是key-value只能是字符串,不能是其他对象。

如果你想存入其他类型的数据,需要自己定义一个RedisTemplate对象,返回一个自己想要的RedisTemplate对象,自己定义序列化方式。

上述两个步骤完成后,SpringBoot自动在Spring容器中配置一个redisTemplate的Bean,所以可以直接使用redisTemplate

StringRedisTemplate和RedisTemplate 区别

StringRedisTemplate和RedisTemplate的区别及使用方法
参考URL: https://www.cnblogs.com/MyYJ/p/10778874.html
StringRedisTemplate和RedisTemplate区别和联系
参考URL: https://jingyan.baidu.com/article/f7ff0bfcc5c4152e26bb13bc.html

StringRedisTemplate和RedisTemplate的区别及使用方法,使用时只需使用maven依赖包spring-boot-starter-data-redis即可,然后在service中注入StringRedisTemplate或者RedisTemplate即可。

在这里插入图片描述

  • StringRedisTemplate继承了RedisTemplate,所以两者对Redis的操作方法具有相同之处
  • 两者的数据是不共通的;也就是说StringRedisTemplate只能管理StringRedisTemplate里面的数据,RedisTemplate只能管理RedisTemplate中的数据。
  • 各自序列化的方式不同
    StringRedisTemplate使用的是StringRedisSerializer类;RedisTemplate使用的是JdkSerializationRedisSerializer类。反序列化,则是一个得到String,一个得到Object
  • StringRedisTemplate只能对key=String,value=String的键值对进行操作,RedisTemplate可以对任何类型的key-value键值对操作。

总结: 当你的redis数据库里面本来存的是字符串数据或者你要存取的数据就是字符串类型数据的时候,那么你就使用StringRedisTemplate即可,
但是如果你的数据是复杂的对象类型,而取出的时候又不想做任何的数据转换,直接从Redis里面取出一个对象,那么使用RedisTemplate是更好的选择。

2. RedisTemplate使用姿势

在Java中使用redisTemplate操作缓存的方法示例
参考URL: http://www.uxys.com/html/JavaKfjs/20200118/2055.html

针对不同的数据结构(String, List, ZSet, Hash)读封装了比较使用的调用方式 opsForXXX

// hash 数据结构操作
org.springframework.data.redis.core.RedisTemplate#opsForHash
 
// list
org.springframework.data.redis.core.RedisTemplate#opsForList
 
// string
org.springframework.data.redis.core.RedisTemplate#opsForValue
 
// set
org.springframework.data.redis.core.RedisTemplate#opsForSet
 
// zset
org.springframework.data.redis.core.RedisTemplate#opsForZSet

常用方法:
RedisTemplate常用方法总结
参考URL: https://blog.csdn.net/sinat_22797429/article/details/89196933
RedisTemplate最全的常用方法总结
参考URL: https://blog.csdn.net/yang_hui_liang/article/details/97900048

举例:opsForHash

1、put(H key, HK hashKey, HV value)
 

   新增hashMap值。

   

Java代码  收藏代码

redisTemplate.opsForHash().put("hashValue","map1","map1-1");  
redisTemplate.opsForHash().put("hashValue","map2","map2-2");  
 

     2、values(H key)
 

  获取指定变量中的hashMap值。

 

Java代码  收藏代码

List<Object> hashList = redisTemplate.opsForHash().values("hashValue");  
System.out.println("通过values(H key)方法获取变量中的hashMap值:" + hashList);  
 

3. 常见问题

Springboot操作Redis时,发现key值出现 \xac\xed\x00\x05t\x00\tb

SpringBoot项目使用RedisTemplate遇到key值\xac\…
参考URL: https://www.cnblogs.com/fatmanhappycode/p/12231192.html

原因分析:
spring-data-redis的RedisTemplate<K, V>模板类在操作redis时默认使用JdkSerializationRedisSerializer来进行序列化。

JdkSerializationRedisSerializer把传入的值当Object对象进行序列化,所以可以猜测这里key出现的\xac\xed\x00\x05t\x00\tb其实可能是对象头信息。

凡是用到存到redis的数据,都需要序列化,如果用redis默认的序列化类,会导致存到redis数据库的数据可读性不太好。虽然保存的key和我们想象中的不太一样,但是并不影响我们调用。

解决方法:更改序列化方式,或者也可直接使用 StringRedisTemplate

五、spring 环境下使用RedisTemplate

spring-data-redis的基本使用
参考URl: https://blog.csdn.net/weixin_42333583/article/details/82624169

​ Spring-data-redis是spring大家族的一部分,提供了在srping应用中通过简单的配置访问redis服务,对reids底层开发包(Jedis, JRedis, and RJC)进行了高度封装,RedisTemplate提供了redis各种操作、异常处理及序列化,支持发布订阅,并对spring 3.1 cache进行了实现。

spring-data-redis针对jedis提供了如下功能:

连接池自动管理,提供了一个高度封装的“RedisTemplate”类

针对jedis客户端中大量api进行了归类封装,将同一类型操作封装为operation接口

    ValueOperations:简单K-V操作

    SetOperations:set类型数据操作

    ZSetOperations:zset类型数据操作

    HashOperations:针对map类型的数据操作

    ListOperations:针对list类型的数据操作
  1. 第一步: 在pom文件中需要导入:spring相关的jar包,srping-data-redis的包
            <dependency>
                <groupId>org.springframework.data</groupId>
                <artifactId>spring-data-redis</artifactId>
                <version>1.8.6.RELEASE</version>
            </dependency>
    
  2. 第二步:引入spring-data-redis的配置文件 redis-config.properties
  3. 第三步:在applicationContext_redis.xml中配置配置文件

本节 未验证测试,具体参考原作者URL。

六、redis基础

Redis的hash数据类型和应用场景

Redis的hash数据类型及其应用场景解析—购物车
参考URL: https://blog.csdn.net/ahjxhy2010/article/details/79892894

Redis中的Hashes类型可以看成具有String Key和String Value的map容器

在这里插入图片描述

  • hset

描述:将哈希表key中的域field的值设为value。如果key不存在,一个新的哈希表被创建并进行HSET操作。如果域field已经存在于哈希表中,旧值将被覆盖。

参数:key field value

返回值:如果field是哈希表中的一个新建域,并且值设置成功,返回1。如果哈希表中域field已经存在且旧值已被新值覆盖,返回0。

  • hmset

描述:同时将多个field - value(域-值)对设置到哈希表key中。此命令会覆盖哈希表中已存在的域。如果key不存在,一个空哈希表被创建并执行HMSET操作。

参数:key field value [field value …]

返回值:如果命令执行成功,返回OK。当key不是哈希表(hash)类型时,返回一个错误。

  • hmget

描述:返回哈希表key中,一个或多个给定域的值。如果给定的域不存在于哈希表,那么返回一个nil值。因为不存在的key被当作一个空哈希表来处理,所以对一个不存在的key进行HMGET操作将返回一个只带有nil值的表。

参数:key field [field …]

返回值:一个包含多个给定域的关联值的表,表值的排列顺序和给定域参数的请求顺序一样。

  • hgetall

描述:返回哈希表key中,所有的域和值。在返回值里,紧跟每个域名(field name)之后是域的值(value),所以返回值的长度是哈希表大小的两倍。

参数:key

返回值:以列表形式返回哈希表的域和域的值。 若key不存在,返回空列表。

七、Redis 开发规范(redis键值设计)

阿里云 Redis 开发规范深入解读,别只会 set、get!
参考URL: https://mp.weixin.qq.com/s/jy5gGFmbvdVQrIAMHBfGog

个人常用总结:

  1. 建议使用冒号即:进行分割拼接,
    因为很多Redis客户端是根据冒号分类的。比如有几个Key:apps:app:1、apps:app:2和apps:app:3。Redis Desktop Manager能自动归类到apps目录下。

另: Redis desktop manager之类的工具中可以设置分割字符。

  1. 设置优雅的key

Redis的Key虽然可以自定义,但最好遵循下面的几个最佳实践约定:

  • 遵循基本格式:[业务名称]:[数据名]:[id]
  • 长度不超过44字节
    Redis的embstr编码方式和raw编码方式在3.0版本之前是以39字节为分界的,也就是说,如果一个字符串值的长度小于等于39字节,则按照embstr进行编码,否则按照raw进行编码。 参考文章
    而在3.2版本之后,则变成了44字节为分界。
  • 不包含特殊字符

例如:登录业务,保存用户信息。login:user:10

优点:

  • 可读性强
  • 避免key冲突
  • 方便管理
  • 更节省内存: key是string类型,底层编码包含int、embstr和raw三种。embstr在小于44字节使用,采用连续内存空间,内存占用更小

为什么字符串emstr的字符串长度是44字节上限?
测试key长度对Redis性能影响

保证语义的前提下,控制key的长度,当key较多时,内存占用也不容忽视

八、 如何管理 redis key 的名字比较好?

Java 项目里如何管理 redis key 的名字比较好?
参考URL: https://segmentfault.com/q/1010000010400076?sort=created
RedisKey Template 管理
参考URL: https://www.jianshu.com/p/a6ad097a3cd5

思路总结

  • 思路1: 自定义一个 constant 类,用 public final static String 变量存 key 命名的固定部分
    譬如 read_book_by_user:user_id:3423211 那么

    public class RedisKeyConstants{
    
    public final static String READ_BOOK_BY_USER = "read_book_by_user:user_id:";
    }
    

    用的时候
    redisTemplate.opsForValue.get(READ_BOOK_BY_USER+user.getId());

    或者

    public class RuleConstant {
        /**
         * redis key 当前价格
         */
        public static final String TICK_PRICE = "symbol:%s:current-price";
    
  • 思路2:写个KeyBuilder 返回个Rediskey类,
    把对应操作的String key换成Rediskey key
    项目前缀和模块前缀都可以在KeyBuilder维护好。

  1. 创建KeyTemplate枚举
public enum RedisKey {

    /**
     * 日开盘价 key
     */
    DAY_OPEN_PRICE("symbol:yyyy-MM-dd:open-price:{}:{}:{}",new String[]{ "symbol", "day", "openPrice"}),
    /**
     * 当前价格
     */
    TICK_PRICE("symbol:current-price:{}:{}",new String[]{ "symbol", "price"}),
    UK("TEST:{userId}:TYPE:{name}", new String[]{ "userId", "name" });

    public String keyTemplate;
    public String[] keyNames;

    RedisKey(String keyTemplate, String[] keyNames) {
        this.keyTemplate = keyTemplate;
        this.keyNames = keyNames;
    }
}
  1. 创建KeyBuilder
import java.util.HashMap;
import java.util.Map;

public class RedisKeyBuilder {

    public static String build(RedisKey redisKey, Map<String, String> params) {
        String key = redisKey.keyTemplate;
        String[] keyNames = redisKey.keyNames;
        for (String keyName : keyNames) {
            String param = params.get(keyName);
            param = param==null?"*":param;

            key = key.replace("{"+ keyName +"}", param);
        }
        return key;
    }

    public static void main(String[] args) {
        Map<String, String> params = new HashMap<>();
        params.put("userId", "0");
        params.put("name", "疾风剑豪");

        String build = RedisKeyBuilder.build(RedisKey.UK, params);
        System.out.println(build);

        String xx = String.format("sss%s","aa");
        System.out.println(xx);
    }
}

总结: 个人感觉第一种好一点,比较简单,说白了就是一个key格式化问题,思路2中原作者的实现有问题,build内部写的比较死,传的参数需要需要特定的枚举类特定name才可以替换。不推荐使用!

思路3:编写工具类,参考日志log.info 中的花括号替换,
该思路和思路1其实一样,只是字符串格式化,使用{}替换String.format 中的%s。

总结:思路1其实简单够用!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

西京刀客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值