一、部署
单机模式(standalone)部署
1. Linux下安装gcc,(用于编译c文件),root用户执行
$ yum install gcc
2. 在/opt下安装redis
$ cd /opt
$ 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 MALLOC=libc
3. 启动reids
$ src/redis-server (redis-server在编译成功后才生成)
出现的错误,将"$ make"命令改成"$ make MALLOC=libc" 即可
reids启动后界面,不能退出,否则就关闭了:(如下,可以以守护进程方式启动)
4. 配置redis以守护进程方式启动
$ vi /opt/redis-5.0.5/redis.conf
按键"shift :",进入底线命令行模式,查找"daemonize"单词,如下
:/daemonize (回车)
找到后,按键"i",进入编辑模式,修改 daemonize yes,保存退出
5. 以配置文件启动reids,这是就能以守护进程方式启动了
$ cd /opt/redis-5.0.5
$ src/redis-server redis.conf
查看是否启动
$ ps aux | grep reids-server
6. 使用客户端交互
$ /opt/redis-5.0.5/src/redis-cli
注:(默认无密码登陆)如果登陆设置了密码,需要输入密码,否则无权访问
127.0.0.1:6379> auth 123456
OK
新增
127.0.0.1:6379> set foo bar
OK
获取
127.0.0.1:6379> get foo
"bar"
删除
127.0.0.1:6379> del foo
(integer) 1
127.0.0.1:6379> get foo
(nil)
关闭redis服务(通过客户端关闭)
127.0.0.1:6379> shutdown
退出客户端
127.0.0.1:6379> exit (连接时退出客户端)
not connected> exit (未连接时退出客户端)
** 配置文件redis.conf
配置1:
bind 127.0.0.1 (默认配置)
意为:禁止外网访问,只允许本地访问
bind 127.0.0.1 192.168.190.200
意为:允许多个IP访问(用空格分隔)
bind 0.0.0.0
意为:允许任意IP访问
配置2:
requirepass foobared (默认注释掉,无密码登陆)
意为:授权登陆密码,需要设置复杂强度高的密码,否则由于其高性能并发性,容易被碰撞破解
本地测试用,可以设为:
requirepass 123456
配置3:
daemonize yes
意为:以守护进程方式后台启动运行
二、Redis客户端 Jedis使用(Scala实现)
package sparkstreaming_action.userbehavior.dao
import redis.clients.jedis.Jedis
import redis.clients.jedis.exceptions.JedisConnectionException
import scala.collection.mutable.ArrayBuffer
import org.apache.log4j.LogManager
import sparkstreaming_action.userbehavior.util.Conf
/**
* *Redis 客户端编程 主页:https://redis.io/clients
* 以下是相关推荐:
* (推荐)jedis 源码及教程:https://github.com/xetorthio/jedis/wiki
* oschina jedis 2.1.0 API 使用手册:http://tool.oschina.net/uploads/apidocs/redis/clients/jedis/Jedis.html
* (推荐)scala-redis 源码:https://github.com/debasishg/scala-redis
* spark-redis 源码:https://github.com/RedisLabs/spark-redis/blob/master/doc/getting-started.md
* sedis 源码:https://github.com/pk11/sedis
*/
/**
* Redis util
*/
object RedisUtil {
@transient lazy val log = LogManager.getLogger(this.getClass)
/**
* Redis 读写分离
*/
// Redis 客户端 读连接
var readJedis: Jedis = _
// Redis 客户端 写连接
var writeJedis: Jedis = _
/** 验证 Redis 连接是否可用,不可用时重连
* @return Unit
*/
def checkAlive: Unit = {
// 读连接验证
if (!isConnected(readJedis)) {
readJedis = reConnect(readJedis)
}
// 写连接验证
if (!isConnected(writeJedis)) {
writeJedis = reConnect(writeJedis)
}
}
/**
* 获取 Redis 客户端连接
* @param ip Redis server host
* @param port Redis server port
* @param passwd Redis授权连接密码
* @return Jedis 返回Redis客户端访问对象
*/
def getConn(ip: String, port: Int, passwd: String): Jedis = {
// 创建 Jedis连接,连接超时时间:5000ms
val jedis = new Jedis(ip, port, 5000)
jedis.connect
// 设置登陆密码
if (passwd != null && passwd.length() > 0) {
/** 连接 Redis 密码,需要设置高强度一点、长一点
* 由于Redis的高性能特性,很有可能利用并发在短时间内尝试很多密码,造成密码破译
*/
jedis.auth(passwd)
}
jedis
}
/** 判断 Redis 客户端是否连接
* @param jedis Redis 客户端
* @return Boolean true|false
*/
def isConnected(jedis: Jedis): Boolean = jedis != null && jedis.isConnected()
/** 重连 Redis 客户端
* @param jedis 原 Redis 客户端
* @return jedis 重连后的 Redis 客户端
*/
def reConnect(jedis: Jedis): Jedis = {
println("reconnecting ...")
disConnect(jedis)
getConn(Conf.redisIp, Conf.redisPort, Conf.passwd)
}
/** 释放 Redis 客户端连接
* @param jedis Redis 客户端
* @return Unit
*/
def disConnect(jedis: Jedis): Unit = {
if (jedis != null && jedis.isConnected()) {
jedis.close()
}
}
/** 键值对 批量 写入 Redis 存储
* @param kvs 键值对二元组列表(键值对需转成字节数组存储)
* @return Unit
*/
def batchSet(kvs: Seq[(Array[Byte], Array[Byte])]): Unit = {
try {
// 检查连接
checkAlive
// 遍历键值对列表
var i = 0
while (i < kvs.length) {
/**
* 每 batchSize 条插入命令,作为一个批次执行
* 每一批次执行,通过获取一个管道实现
*/
// 获取管道,便于一次执行大量命令
val pipeline = writeJedis.pipelined()
// 每批发送指定数量(batchSize)命令
val target = i + Conf.batchSize
println(s"set ${new String(kvs(i)._1)} to ${new String(kvs(i)._2)}")
while (i < target && i < kvs.length) {
// 插入键值对命令
pipeline.set(kvs(i)._1, kvs(i)._2)
// 设置键超时命令(意味着此键是不稳定的,到期后键会被 Redis server 删除)
pipeline.expire(kvs(i)._1, Conf.EXPIRE_DURATION)
i += 1
}
// 读取所有指令响应同步到管道,并关闭此管道
pipeline.sync()
}
} catch {
case connEx: JedisConnectionException =>
log.error("[batchSet_connError]", connEx)
// 连接异常时,重连
writeJedis = reConnect(writeJedis)
case ex: Exception =>
log.error("[batchSet_Error]", ex)
}
}
/** 按键 批量 读出 Redis 存储值
* @param keys 键列表
* @return 批量返回键对应的值列表(字节数组列表)
*/
def batchGet(keys: Seq[String]): ArrayBuffer[Array[Byte]] = {
// 定义返回的值列表
val res = ArrayBuffer[Array[Byte]]()
try {
// 检查连接
checkAlive
// 遍历键列表
var i = 0
while (i < keys.length) {
// 获取键的值
val resp = readJedis.get(keys(i).getBytes)
res += resp
i += 1
}
} catch {
case connEx: JedisConnectionException =>
log.error("[batchGet_connError]", connEx)
// 连接异常时,重连
readJedis = reConnect(readJedis)
case ex: Exception =>
log.error("[batchGet_Error]", ex)
}
res
}
}
参考文章:
3. redis安装zmalloc.h:50:31: 致命错误:jemalloc/jemalloc.h:没有那个文件或目录