markdown Redis的

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了markdown Redis的相关的知识,希望对你有一定的参考价值。

# REDIS
* REmote DIctionary Server
1. key/value _store_
2. Built-in support for data structures like hashes
3. Performs well as a _cache store_ and a full-fledged NoSQL data store

## Installing  Redis
* `brew install redis` on OSX
* To have launchd start redis now and restart at login: `brew services start redis`
* If you don't want/need a background service: `redis-server /usr/local/etc/redis.conf` (use!)
* Use in a rails app: `gem install redis`
---

## How does caching work?
*  Disk access is expensive!
*  Disk access also negatively impacts performance!
    * To counter this, implement a caching layer between your application and database server
* Initially, a caching layer **doesn't contain any data at first**!
    * When it receives the request for the data, it calls the database and stores the result 
    in memory
    * Later requests won't need to access the database because the data is already stored in
    the cache!

---

## Model Caching using Redis
* Create a simple app using scaffold `Snippet content:text`
* In this example, redis will be used to load snippets from Rails rather than using a SQL db.
* For loading a page that contains many records, it may take a very long time to load, Redis can
be used to load the records **drastically faster**
* Once the app is created and migrations are ran, install the following gems:
    * `gem 'rack-mini-profiler'`: displays loading time in upper left corner of browser
    * `gem 'faker'`: used to fill in dummy data to create records faster
    
    ```ruby
    #example of using faker in seed.db
    100000.times do 
      Snippet.create(content: Faker::Lorem.paragraph)
    end
    ```
* `bundle install`
* `bundle exec rake db:seed`
* Change root to `snippets#index`
* Run `rails s`
* Notice the loading time of rack-mini-profiler!

---

## Using Redis as a cache store
* Open terminal, in one window run `redis-server`
    * Make an alias in your bash_profile: **`redis-server /usr/local/etc/redis.conf`** 
* Add the following gems to `Gemfile`:
    * `gem 'redis'`
    * `gem 'redis-rails'`
* `bundle install`
* In `config/development.rb`, you can instruct Rails to use redis as a cache store: (or even `production.rb`)

```ruby
module nameOfApp
  class Application < Rails::Application
    config.cache_store = :redis_store, 'redis://localhost:6379/0/cache', {expires_in: 90.minutes}
    # redis has 16 databases to choose from (0-15), represents the 0 before cache
    # cache represents the namespace
    # you can configure host, port and other db:
    # Redis.new(:host => '10.0.1.1', :port => 6380, :db => 15)
    # Alternatively: 
    config.cache_store = :redis_store, {
      host: 'localhost',
      port: 6379,
      db: 0,
      namespace: 'cache'
    }
  end
end
```

* Restart your app any time you makes changes to these files!

---

### Application Modifications
* Configuring and setting up redis is now complete!
* Instead of loading records from the SQL database, head in to a controller that loads records:

```ruby
#include the controller helper folder, code will be ran inside there
# example SnippetsController.rb
def index
  @data = fetch_snippets
end

#helpers/snippets_helper.rb

module SnippetsHelper
  def fetch_snippets
    snippets = $redis.get("snippets")
    if snippets.nil?
      #IMPORTANT: 
      # the first time around snippets will be nil, redis hasn't put anything in yet
      snippets = Snippet.all.to_json
      
      #Now redis is inserting the array of snippets in a hash with key "snippets"
      # from the database access, so that next time it can just bypass the db and use its store 
      $redis.set("snippets", snippets)
      
      #Expire the cache every 5 hours
      $redis.expire("snippets", 5.hour.to_i)
      end
    JSON.load snippets
  end
end

#Update the views

<% @data.each do |snippet| %>

  <%= snippet["content"] %>

<% end %>

```

* **_Why convert the data received from the db?_** The fastest way to write objects to redis.
    * Alternative is to iterate over all the objects and then save them as a hash = SLOW
    * Fastest way is to save them as a JSON encoded string, to decode use `JSON.load`
    * This alters the returned data so we will need to change the views to access attributes
    as a hash (as above)
* Restart server and refresh page to notice the change in loading time!
* If you make a change to a model, redis will wait the amount specified to expire befor
getting fresh data. You can create a `after_save` validation on the model being cached:

```ruby
#example of categories being cached
class Category

  after_save: :clear_cache
  
  def clear_cache
    $redis.del "categories"
  end
  
end
```
* Now, when a model is updated (and saved to the db) Rails is instructed to clear the cache,
ensuring that the cache is always upto date.

---

## Redis Rails
* in gemfile: `gem 'redis-rails'`

```ruby
# setting a key/value pair 
redis.set("key", "value")

# retrieving a value
redis.get("key")
#=> "value"


# in your rails app, view template
<% cache 'word-of-the-hour', :expires_in => Time.now.beginning_of_hour + 1.hour do %>
  <%= %w(ruby rails javascript web developer).sample %>
<% end %>

# Every hour, redis will empty the cache and set a new value for the key
```
## Redis (Overview)
* Install Redis [link](http://redis.io)
* After installation run `redis server`
* In a new tab, run `redis-cli`
    * You can see the redis url: `127.0.0.1:6379`, default port is 6379
* Simple commands:

```ruby
# set key value
set name parm

# get value from key
get name 
# => parm
```

---

## Redis Basics
### Datatypes
* key/value pair
* string
* list (list of ORDERED strings)
* hashes
* set (list of UNORDERED  and UNIQUE strings)

### Redis Persistence Options
* Data is saved in memory for fast access!
* Two options:
    * **AOF** (Append-only File): logs every operation in the system file. If the log gets too 
    large, Redis will be able to shrink it down to only the latest version of the file.
    * **RDB** (Redis Database File): creates a snapshot, creating copies of moments in time.
    (Default)
* Configuring which option to use: 
    * `cd` in to the directory where you downloaded redis
    * Open `redis.config`, find section for `Snapshotting`, read the info on how to configure
    the snapshot after x sec with atleast x amount of changes
    * Find section for `appendonly` and change `no` to `yes`
    * Save & close, copy the path to the file
    * Restart the server and this time append the path to it: 
    `redis-server /usr/local/etc/redis.conf`

### Replication
* Copy and rename the above file as `redis2.conf`
    * change the port number to `3780`
    * find `slaveof` and replace with: `slaveof 127.0.0.1 6379`, _slave of `redis.config`_
    * Open a new tab and start another server with the `redis2.conf` file
    * Should notice `master-slave relation has started`

### Security
* Open both `.conf` files
* find `requirepass enterpass`, replace `enterpass` with a password, make sure slave is updated
with the same password in the location of `masterauth`
* restart both servers for each to take effect!
* In order to use the cli, enter the following: `redis-cli -a password`, entering the password
that was set in the `.conf` file.

### Datasets using Keys

```ruby
set address 435

incr address #increment by 1
# => 436

incrby address 100 #increment by x

#decrement
decr address
decrby address

# For multiple words for a value, USE DOUBLE QUOTES!!
set country "North America"

#getset is used to get a key and then set it, returns original key
getset firstName "Parm"

#set multiple values:
mset street blah city blah2 state blah3 zip "blah4"

#retrieve those values:
mget street city state zip

#check if something exists:
exists street
# returns 1 for yes it exists, 0 else

#delete a key
del street

#expire a key in x sec
exp city 5

#set and expires
set zip "989-899989" ex 9
```

### Hash

```ruby
#creating a hash:
hmset nameofhash key1 value1 key2 value2 ...

#retrieve the hash:
hgetall nameofhash

#retrieve a certain value in the hash:
hget nameofhash key1

#retrieve multiple values
hmget nameofhash key1 key2

#exist?
hexist nameofhash  key1

#set another key
hmset nameofhash keyx valuex

#increment
hincrby nameofhash key numtoincrementby
```

### Lists

```ruby
#creates a new list (right push appends to bottom of list)
rpush nameoflist value1 value2 value3 ...

#list the list
lrange nameoflist startindex stopindex
#startindex is usually 0!
# -1 all 
# -2 all except the last one
# -3 all except the last 2

#append to the BEGINNING of a list (left push)
lpush nameoflist valuex

#remove (left pop)
lpop nameoflist

#right pop (removes at the end of the list)
rpop nameoflist

#trimming a list
ltrim nameoflist starti stopi
#ex ltrim grocery 0 2
# lrange 0 -1 to see the new list
```

### Sets

```ruby
#creating a set
sadd nameofset value1 value2 value3 value4

#retrieve set
smembers name

#add more values
sadd valuex valauey

#is there?
sismember nameofset value
#returns 0 no, 1 yes

#creating a subset
sadd nameofset:value value_1 value_2 value_3 ...

#retrieve subset
smembers nameofset:value

#creating a new value that has the same sublist as another value
sunionstore nameofset:newvalue nameofset:existingvalue

#remove the last value from the subset
spop nameofset:value

#count of how many values
scard nameofset
```

### Sorted Sets

```ruby
#creating a sorted set, helps if keys are integers
zadd nameofset key1 value1 key2 value2 key3 value3 ...

#listing the set
zrange nameofset starti endi
# 0 start, -1 end
# return just the values, to return with key AND values:

zrange nameofset 0 -1 withscores #again 0 is starti and -1 is endi

#reverse the set
zrevrange nameofset starti endi withscores

#get upto a certain range of key
zrangebyscore nameofset -inf integer withscores
#inf = information that will be obtained until the integer value

#retrieve the position of a value
zrank nameofset value
#returns the index or ranking

# IF THEY KEYS ARE NOT INTEGERS, REDIS WOULD SORT THE KEYS ALPHABETICALLY

```

---

### Security with Redis
* open the `config` file and search for security, `requirepass password` is the main way to secure
redis
* Next, ensure that redis port and address is firewalled from unrestriced access!
    * Binding redis to a single interface is the standard config and best practice
* Search for `bind` and notice that redis is binded to `127.0.0.1` = 1 interface, which means 
we can only access the redis server through that address!
* It is advised to stray away from adding more than one interface to a single redis server!

以上是关于markdown Redis的的主要内容,如果未能解决你的问题,请参考以下文章

markdown [Redis]同一台服务器上的多个Redis实例#linux

markdown Redis的

markdown Redis的

markdown Redis的

markdown Redis的

markdown Redis的SortedSet的のをコピー